Exemplo n.º 1
0
int jpegenc_init(int w, int h) {
    memset(&jpeg, 0x00, sizeof(jpeg));
    jpeg.size.w = w;
    jpeg.size.h = h;

    pthread_mutex_init(&jpeg.lock, NULL);
    pthread_cond_init(&jpeg.cond, NULL);

    jpeg.handle = jpeg_open(&jpeg.ops, NULL, jpeg.size, NULL);
    if (0 == jpeg.handle) {
        loge("fail to call jpeg_open");
        return -EINVAL;
    }

    /* init parameters */
    jpeg.out.size = w * h * 3 / 2;
    jpeg.out.addr = (uint8_t*)buffer_allocate(&jpeg.out, 0);
    if (NULL == jpeg.out.addr) {
        jpeg.ops.close(jpeg.handle);
        jpeg.handle = 0;
        loge("fail to allocate buffer");
        return -EINVAL;
    }
    jpeg.in.size = w * h * 3 / 2;
    jpeg.in.addr = (uint8_t*)buffer_allocate(&jpeg.out, 0);
    if (NULL == jpeg.in.addr) {
        jpeg.ops.close(jpeg.handle);
        jpeg.handle = 0;
        loge("fail to allocate buffer");
        return -EINVAL;
    }

    return 0;
}
Exemplo n.º 2
0
buffer_t *create_buffer(size_t size)
{
    buffer_t *ret = (buffer_t *)malloc(sizeof(*ret));
    if (0 != buffer_allocate(ret, size)) {
        free(ret);
        ret = NULL;
    }
    return ret;
}
Exemplo n.º 3
0
ATF_TC_BODY(buffer_reference, tc) {

    struct buffer *a, *b;

    /*
     * Create a buffer.
     */
    a = NULL;
    if (!buffer_allocate(&a, 100, MDL)) {
        atf_tc_fail("failed on allocate 100 bytes");
    }

    /**
     * Confirm buffer_reference() doesn't work if we pass in NULL.
     *
     * @TODO: we should confirm we get an error message here.
     */
    if (buffer_reference(NULL, a, MDL)) {
        atf_tc_fail("succeeded on an error input");
    }

    /**
     * @TODO: we should confirm we get an error message if we pass
     *       a non-NULL target.
     */

    /*
     * Confirm we work under normal circumstances.
     */
    b = NULL;
    if (!buffer_reference(&b, a, MDL)) {
        atf_tc_fail("buffer_reference() failed");
    }

    if (b != a) {
        atf_tc_fail("incorrect pointer returned");
    }

    if (b->refcnt != 2) {
        atf_tc_fail("incorrect refcnt");
    }

    /*
     * Clean up.
     */
    if (!buffer_dereference(&b, MDL)) {
        atf_tc_fail("buffer_dereference() failed");
    }
    if (!buffer_dereference(&a, MDL)) {
        atf_tc_fail("buffer_dereference() failed");
    }

}
Exemplo n.º 4
0
static int buffer_make_space(buffer_t *self, int size)
{
    int new_size;

    new_size = self->allocated;
    if (new_size < 4096)
        new_size = 4096;

    while (new_size - self->size < size)
        new_size <<= 1;

    return buffer_allocate(self, new_size);
}
Exemplo n.º 5
0
buffer_desc_t *
page_set_extend (dbe_storage_t * dbs, buffer_desc_t ** set, dp_addr_t dp, int flag)
{
  buffer_desc_t * buf, * last = page_set_last (*set);
  buf = buffer_allocate (flag);
  memset (buf->bd_buffer + DP_DATA, 0, PAGE_DATA_SZ);
  buf->bd_page = buf->bd_physical_page = dp;
  buf->bd_storage = dbs;
  if (!last)
    *set = buf;
  else
    last->bd_next = buf;
  return buf;
}
Exemplo n.º 6
0
ATF_TC_BODY(data_string_forget, tc) {
    struct buffer *buf;
    struct data_string a;
    const char *str = "Lorem ipsum dolor sit amet turpis duis.";

    /*
     * Create the string we want to forget.
     */
    memset(&a, 0, sizeof(a));
    a.len = strlen(str);
    buf = NULL;
    if (!buffer_allocate(&buf, a.len, MDL)) {
        atf_tc_fail("out of memory");
    }
    if (!buffer_reference(&a.buffer, buf, MDL)) {
        atf_tc_fail("buffer_reference() failed");
    }
    a.data = a.buffer->data;
    memcpy(a.buffer->data, str, a.len);

    /*
     * Forget and confirm we've forgotten.
     */
    data_string_forget(&a, MDL);

    if (a.len != 0) {
        atf_tc_fail("incorrect length");
    }

    if (a.data != NULL) {
        atf_tc_fail("incorrect data");
    }
    if (a.terminated) {
        atf_tc_fail("incorrect terminated");
    }
    if (a.buffer != NULL) {
        atf_tc_fail("incorrect buffer");
    }
    if (buf->refcnt != 1) {
        atf_tc_fail("too many references to buf");
    }

    /*
     * Clean up buffer.
     */
    if (!buffer_dereference(&buf, MDL)) {
        atf_tc_fail("buffer_reference() failed");
    }
}
Exemplo n.º 7
0
ATF_TC_BODY(buffer_allocate, tc) {
    struct buffer *buf = 0;

    /*
     * Check a 0-length buffer.
     */
    buf = NULL;
    if (!buffer_allocate(&buf, 0, MDL)) {
        atf_tc_fail("failed on 0-len buffer");
    }
    if (!buffer_dereference(&buf, MDL)) {
        atf_tc_fail("buffer_dereference() failed");
    }
    if (buf != NULL) {
        atf_tc_fail("buffer_dereference() did not NULL-out buffer");
    }

    /*
     * Check an actual buffer.
     */
    buf = NULL;
    if (!buffer_allocate(&buf, 100, MDL)) {
        atf_tc_fail("failed on allocate 100 bytes\n");
    }
    if (!buffer_dereference(&buf, MDL)) {
        atf_tc_fail("buffer_dereference() failed");
    }
    if (buf != NULL) {
        atf_tc_fail("buffer_dereference() did not NULL-out buffer");
    }

    /*
     * Okay, we're happy.
     */
    atf_tc_pass();
}
Exemplo n.º 8
0
/**
 *  @brief sets client-id field in host declaration
 *
 *  @param host pointer to host declaration
 *  @param uid pointer to client-id data
 *  @param uid_len length of the client-id data
 *
 *  @return 1 if successful, 0 otherwise
 */
int lease_set_clientid(struct host_decl *host, const unsigned char *uid, int uid_len) {

    /* clean-up this mess and set client-identifier in a sane way */
    int real_len = uid_len;
    if (uid_len == 0) {
        real_len = strlen((const char *)uid) + 1;
    }

    memset(&host->client_identifier, 0, sizeof(host->client_identifier));
    host->client_identifier.len = uid_len;
    if (!buffer_allocate(&host->client_identifier.buffer, real_len, MDL)) {
        return 0;
    }
    host->client_identifier.data = host->client_identifier.buffer->data;
    memcpy((char *)host->client_identifier.data, uid, real_len);

    return 1;
}
Exemplo n.º 9
0
int mm_jpegdec_test_alloc(buffer_t *p_buffer, int use_pmem)
{
  int ret = 0;
  /*Allocate buffers*/
  if (use_pmem) {
    p_buffer->addr = (uint8_t *)buffer_allocate(p_buffer, 0);
    if (NULL == p_buffer->addr) {
      CDBG_ERROR("%s:%d] Error",__func__, __LINE__);
      return -1;
    }
  } else {
    /* Allocate heap memory */
    p_buffer->addr = (uint8_t *)malloc(p_buffer->size);
    if (NULL == p_buffer->addr) {
      CDBG_ERROR("%s:%d] Error",__func__, __LINE__);
      return -1;
    }
  }
  return ret;
}
Exemplo n.º 10
0
ATF_TC_BODY(data_string_copy, tc) {
    struct data_string a, b;
    const char *str = "Lorem ipsum dolor sit amet orci aliquam.";

    /*
     * Create the string we want to copy.
         */
    memset(&a, 0, sizeof(a));
    a.len = strlen(str);
    if (!buffer_allocate(&a.buffer, a.len, MDL)) {
        atf_tc_fail("out of memory");
    }
    a.data = a.buffer->data;
    memcpy(a.buffer->data, str, a.len);

    /*
     * Copy the string, and confirm it works.
     */
    memset(&b, 0, sizeof(b));
    data_string_copy(&b, &a, MDL);

    if (b.len != a.len) {
        atf_tc_fail("incorrect length");
    }
    if (b.data != a.data) {
        atf_tc_fail("incorrect data");
    }
    if (b.terminated != a.terminated) {
        atf_tc_fail("incorrect terminated");
    }
    if (b.buffer != a.buffer) {
        atf_tc_fail("incorrect buffer");
    }

    /*
     * Clean up.
     */
    data_string_forget(&b, MDL);
    data_string_forget(&a, MDL);
}
Exemplo n.º 11
0
/*
 * Set an error in a status-code option (from set_status_code).
 */
static int
set_error(struct lq6_state *lq, u_int16_t code, const char *message) {
	struct data_string d;
	int ret_val;

	memset(&d, 0, sizeof(d));
	d.len = sizeof(code) + strlen(message);
	if (!buffer_allocate(&d.buffer, d.len, MDL)) {
		log_fatal("set_error: no memory for status code.");
	}
	d.data = d.buffer->data;
	putUShort(d.buffer->data, code);
	memcpy(d.buffer->data + sizeof(code), message, d.len - sizeof(code));
	if (!save_option_buffer(&dhcpv6_universe, lq->reply_opts,
				d.buffer, (unsigned char *)d.data, d.len, 
				D6O_STATUS_CODE, 0)) {
		log_error("set_error: error saving status code.");
		ret_val = 0;
	} else {
		ret_val = 1;
	}
	data_string_forget(&d, MDL);
	return ret_val;
}
Exemplo n.º 12
0
/// @brief executes uid hash test for specified client-ids (2 hosts)
///
/// Creates two host structures, adds first host to the uid hash,
/// then adds second host to the hash, then removes first host,
/// then removed the second. Many checks are performed during all
/// operations.
///
/// @param clientid1 client-id of the first host
/// @param clientid1_len client-id1 length (may be 0 for strings)
/// @param clientid2 client-id of the second host
/// @param clientid2_len client-id2 length (may be 0 for strings)
void lease_hash_test_2hosts(unsigned char clientid1[], size_t clientid1_len,
                            unsigned char clientid2[], size_t clientid2_len) {

    printf("Checking hash operation for 2 hosts: clientid1-len=%lu"
           "clientid2-len=%lu\n", (unsigned long) clientid1_len,
           (unsigned long) clientid2_len);

    dhcp_db_objects_setup ();
    dhcp_common_objects_setup ();

    /* check that there is actually zero hosts in the hash */
    /* @todo: host_hash_for_each() */

    struct host_decl *host1 = 0, *host2 = 0;
    struct host_decl *check = 0;

    /* === step 1: allocate hosts === */
    ATF_CHECK_MSG(host_allocate(&host1, MDL) == ISC_R_SUCCESS,
                  "Failed to allocate host");
    ATF_CHECK_MSG(host_allocate(&host2, MDL) == ISC_R_SUCCESS,
                  "Failed to allocate host");

    ATF_CHECK_MSG(host_new_hash(&host_uid_hash, HOST_HASH_SIZE, MDL) != 0,
                  "Unable to create new hash");

    ATF_CHECK_MSG(buffer_allocate(&host1->client_identifier.buffer,
                                  clientid1_len, MDL) != 0,
                  "Can't allocate uid buffer for host1");

    ATF_CHECK_MSG(buffer_allocate(&host2->client_identifier.buffer,
                                  clientid2_len, MDL) != 0,
                  "Can't allocate uid buffer for host2");

    /* setting up host1->client_identifier is actually not needed */
    /*
    ATF_CHECK_MSG(lease_set_clientid(host1, clientid1, actual1_len) != 0,
                  "Failed to set client-id for host1");

    ATF_CHECK_MSG(lease_set_clientid(host2, clientid2, actual2_len) != 0,
                  "Failed to set client-id for host2");
    */

    ATF_CHECK_MSG(host1->refcnt == 1, "Invalid refcnt for host1");
    ATF_CHECK_MSG(host2->refcnt == 1, "Invalid refcnt for host2");

    /* verify that our hosts are not in the hash yet */
    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid1,
                                   clientid1_len, MDL) == 0,
                   "Host1 is not supposed to be in the uid_hash.");

    ATF_CHECK_MSG(!check, "Host1 is not supposed to be in the uid_hash.");

    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid2,
                                   clientid2_len, MDL) == 0,
                  "Host2 is not supposed to be in the uid_hash.");
    ATF_CHECK_MSG(!check, "Host2 is not supposed to be in the uid_hash.");


    /* === step 2: add first host to the hash === */
    host_hash_add(host_uid_hash, clientid1, clientid1_len, host1, MDL);

    /* 2 pointers expected: ours (host1) and the one stored in hash */
    ATF_CHECK_MSG(host1->refcnt == 2, "Invalid refcnt for host1");
    /* 1 pointer expected: just ours (host2) */
    ATF_CHECK_MSG(host2->refcnt == 1, "Invalid refcnt for host2");

    /* verify that host1 is really in the hash and the we can find it */
    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid1,
                                   clientid1_len, MDL),
                  "Host1 was supposed to be in the uid_hash.");
    ATF_CHECK_MSG(check, "Host1 was supposed to be in the uid_hash.");

    /* Hey! That's not the host we were looking for! */
    ATF_CHECK_MSG(check == host1, "Wrong host returned by host_hash_lookup");

    /* 3 pointers: host1, (stored in hash), check */
    ATF_CHECK_MSG(host1->refcnt == 3, "Invalid refcnt for host1");

    /* reference count should be increased because we not have a pointer */

    host_dereference(&check, MDL); /* we don't need it now */

    ATF_CHECK_MSG(check == NULL, "check pointer is supposed to be NULL");

    /* 2 pointers: host1, (stored in hash) */
    ATF_CHECK_MSG(host1->refcnt == 2, "Invalid refcnt for host1");

    /* verify that host2 is not in the hash */
    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid2,
                                   clientid2_len, MDL) == 0,
                  "Host2 was not supposed to be in the uid_hash[2].");
    ATF_CHECK_MSG(check == NULL, "Host2 was not supposed to be in the hash.");


    /* === step 3: add second hot to the hash === */
    host_hash_add(host_uid_hash, clientid2, clientid2_len, host2, MDL);

    /* 2 pointers expected: ours (host1) and the one stored in hash */
    ATF_CHECK_MSG(host2->refcnt == 2, "Invalid refcnt for host2");

    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid2,
                                   clientid2_len, MDL),
                  "Host2 was supposed to be in the uid_hash.");
    ATF_CHECK_MSG(check, "Host2 was supposed to be in the uid_hash.");

    /* Hey! That's not the host we were looking for! */
    ATF_CHECK_MSG(check == host2, "Wrong host returned by host_hash_lookup");

    /* 3 pointers: host1, (stored in hash), check */
    ATF_CHECK_MSG(host2->refcnt == 3, "Invalid refcnt for host1");

    host_dereference(&check, MDL); /* we don't need it now */

    /* now we have 2 hosts in the hash */

    /* verify that host1 is still in the hash and the we can find it */
    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid1,
                                   clientid1_len, MDL),
                  "Host1 was supposed to be in the uid_hash.");
    ATF_CHECK_MSG(check, "Host1 was supposed to be in the uid_hash.");

    /* Hey! That's not the host we were looking for! */
    ATF_CHECK_MSG(check == host1, "Wrong host returned by host_hash_lookup");

    /* 3 pointers: host1, (stored in hash), check */
    ATF_CHECK_MSG(host1->refcnt == 3, "Invalid refcnt for host1");

    host_dereference(&check, MDL); /* we don't need it now */


    /**
     * @todo check that there is actually two hosts in the hash.
     * Use host_hash_for_each() for that.
     */

    /* === step 4: remove first host from the hash === */

    /* delete host from hash */
    host_hash_delete(host_uid_hash, clientid1, clientid1_len, MDL);

    ATF_CHECK_MSG(host1->refcnt == 1, "Invalid refcnt for host1");
    ATF_CHECK_MSG(host2->refcnt == 2, "Invalid refcnt for host2");

    /* verify that host1 is no longer in the hash */
    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid1,
                                   clientid1_len, MDL) == 0,
                   "Host1 is not supposed to be in the uid_hash.");
    ATF_CHECK_MSG(!check, "Host1 is not supposed to be in the uid_hash.");

    /* host2 should be still there, though */
    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid2,
                                   clientid2_len, MDL),
                   "Host2 was supposed to still be in the uid_hash.");
    host_dereference(&check, MDL);

    /* === step 5: remove second host from the hash === */
    host_hash_delete(host_uid_hash, clientid2, clientid2_len, MDL);

    ATF_CHECK_MSG(host1->refcnt == 1, "Invalid refcnt for host1");
    ATF_CHECK_MSG(host2->refcnt == 1, "Invalid refcnt for host2");

    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid2,
                                   clientid2_len, MDL) == 0,
                   "Host2 was not supposed to be in the uid_hash anymore.");

    host_dereference(&host1, MDL);
    host_dereference(&host2, MDL);

    /*
     * No easy way to check if the host object were actually released.
     * We could run it in valgrind and check for memory leaks.
     */

#if defined (DEBUG_MEMORY_LEAKAGE) && defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
    /* @todo: Should be called in cleanup */
    free_everything ();
#endif
}
Exemplo n.º 13
0
Arquivo: gsc.c Projeto: npe9/spin
int gscread  (dev_t dev, struct uio *uio, int ioflag)
{
    int unit = UNIT(minor(dev));
    struct gsc_unit *scu = unittab + unit;
    size_t nbytes;
    int res;

    lprintf("gsc%d.read: minor %d\n", unit, minor(dev));

    if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
    {
        lprintf("gsc%d.read: unit was not attached successfully 0x04x\n",
                unit, scu->flags);
        return ENXIO;
    }

    if ( !(scu->flags & READING) )
    {
        res = buffer_allocate(scu);
        if ( res == SUCCESS )
            scu->flags |= READING;
        else
            return res;

        scu->ctrl_byte = geomtab[scu->geometry].s_res;

        /* initialize for pbm mode */
        if ( scu->flags & PBM_MODE )
        {
            char *p;
            int width = geomtab[scu->geometry].dpl;

            sprintf(scu->sbuf.base,"P4 %d %d\n", width, scu->height);
            scu->bcount = scu->height * width / 8;

            lprintf("gsc%d.read: initializing pbm mode: `%s', bcount: 0x%x\n",
                    unit, scu->sbuf.base, scu->bcount);

            /* move header to end of sbuf */
            for(p=scu->sbuf.base; *p; p++);
            while(--p >= scu->sbuf.base)
            {
                *(char *)(scu->sbuf.base + --scu->sbuf.poi) = *p;
                scu->bcount++;
            }
        }
    }

    lprintf("gsc%d.read(before buffer_read): "
            "size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
            unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount);

    if ( scu->sbuf.poi == scu->sbuf.size )
        if ( (res = buffer_read(scu)) != SUCCESS )
            return res;

    lprintf("gsc%d.read(after buffer_read): "
            "size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
            unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount);

    nbytes = MIN( uio->uio_resid, scu->sbuf.size - scu->sbuf.poi );

    if ( (scu->flags & PBM_MODE) )
        nbytes = MIN( nbytes, scu->bcount );

    lprintf("gsc%d.read: transferring 0x%x bytes", nbytes);

    res = uiomove(scu->sbuf.base + scu->sbuf.poi, nbytes, uio);
    if ( res != SUCCESS )
    {
        lprintf("gsc%d.read: uiomove failed %d", unit, res);
        return res;
    }

    scu->sbuf.poi += nbytes;
    if ( scu->flags & PBM_MODE ) scu->bcount -= nbytes;

    lprintf("gsc%d.read: size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
            unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount);

    return SUCCESS;
}
Exemplo n.º 14
0
/*
 * Process a lease query.
 */
void
dhcpv6_leasequery(struct data_string *reply_ret, struct packet *packet) {
	static struct lq6_state lq;
	struct option_cache *oc;
	int allow_lq;

	/*
	 * Initialize the lease query state.
	 */
	lq.packet = NULL;
	memset(&lq.client_id, 0, sizeof(lq.client_id));
	memset(&lq.server_id, 0, sizeof(lq.server_id));
	memset(&lq.lq_query, 0, sizeof(lq.lq_query));
	lq.query_opts = NULL;
	lq.reply_opts = NULL;
	packet_reference(&lq.packet, packet, MDL);

	/*
	 * Validate our input.
	 */
	if (!valid_query_msg(&lq)) {
		goto exit;
	}

	/*
	 * Prepare our reply.
	 */
	if (!option_state_allocate(&lq.reply_opts, MDL)) {
		log_error("dhcpv6_leasequery: no memory for option state.");
		goto exit;
	}
	execute_statements_in_scope(NULL, lq.packet, NULL, NULL,
				    lq.packet->options, lq.reply_opts,
				    &global_scope, root_group, NULL, NULL);

	lq.buf.reply.msg_type = DHCPV6_LEASEQUERY_REPLY;

	memcpy(lq.buf.reply.transaction_id,
	       lq.packet->dhcpv6_transaction_id,
	       sizeof(lq.buf.reply.transaction_id));

	/* 
	 * Because LEASEQUERY has some privacy concerns, default to deny.
	 */
	allow_lq = 0;

	/*
	 * See if we are authorized to do LEASEQUERY.
	 */
	oc = lookup_option(&server_universe, lq.reply_opts, SV_LEASEQUERY);
	if (oc != NULL) {
		allow_lq = evaluate_boolean_option_cache(NULL,
							 lq.packet,
							 NULL, NULL,
							 lq.packet->options,
							 lq.reply_opts,
							 &global_scope,
							 oc, MDL);
	}

	if (!allow_lq) {
		log_info("dhcpv6_leasequery: not allowed, query ignored.");
		goto exit;
	}
	    
	/*
	 * Same than transmission of REPLY message in RFC 3315:
	 *  server-id
	 *  client-id
	 */

	oc = lookup_option(&dhcpv6_universe, lq.reply_opts, D6O_SERVERID);
	if (oc == NULL) {
		/* If not already in options, get from query then global. */
		if (lq.server_id.data == NULL)
			copy_server_duid(&lq.server_id, MDL);
		if (!save_option_buffer(&dhcpv6_universe,
					lq.reply_opts,
					NULL,
					(unsigned char *)lq.server_id.data,
					lq.server_id.len, 
					D6O_SERVERID,
					0)) {
			log_error("dhcpv6_leasequery: "
				  "error saving server identifier.");
			goto exit;
		}
	}

	if (!save_option_buffer(&dhcpv6_universe,
				lq.reply_opts,
				lq.client_id.buffer,
				(unsigned char *)lq.client_id.data,
				lq.client_id.len,
				D6O_CLIENTID,
				0)) {
		log_error("dhcpv6_leasequery: "
			  "error saving client identifier.");
		goto exit;
	}

	lq.cursor = 4;

	/*
	 * Decode the lq-query option.
	 */

	if (lq.lq_query.len <= LQ_QUERY_OFFSET) {
		if (!set_error(&lq, STATUS_MalformedQuery,
			       "OPTION_LQ_QUERY too short.")) {
			log_error("dhcpv6_leasequery: unable "
				  "to set MalformedQuery status code.");
			goto exit;
		}
		goto done;
	}

	lq.query_type = lq.lq_query.data [0];
	memcpy(&lq.link_addr, lq.lq_query.data + 1, sizeof(lq.link_addr));
	switch (lq.query_type) {
		case LQ6QT_BY_ADDRESS:
			break;
		case LQ6QT_BY_CLIENTID:
			if (!set_error(&lq, STATUS_UnknownQueryType,
				       "QUERY_BY_CLIENTID not supported.")) {
				log_error("dhcpv6_leasequery: unable to "
					  "set UnknownQueryType status code.");
				goto exit;
			}
			goto done;
		default:
			if (!set_error(&lq, STATUS_UnknownQueryType,
				       "Unknown query-type.")) {
				log_error("dhcpv6_leasequery: unable to "
					  "set UnknownQueryType status code.");
				goto exit;
			}
			goto done;
	}

	if (!option_state_allocate(&lq.query_opts, MDL)) {
		log_error("dhcpv6_leasequery: no memory for option state.");
		goto exit;
	}
	if (!parse_option_buffer(lq.query_opts,
				 lq.lq_query.data + LQ_QUERY_OFFSET,
				 lq.lq_query.len - LQ_QUERY_OFFSET,
				 &dhcpv6_universe)) {
		log_error("dhcpv6_leasequery: error parsing query-options.");
		if (!set_error(&lq, STATUS_MalformedQuery,
			       "Bad query-options.")) {
			log_error("dhcpv6_leasequery: unable "
				  "to set MalformedQuery status code.");
			goto exit;
		}
		goto done;
	}

	/* Do it. */
	if (!process_lq_by_address(&lq))
		goto exit;

      done:
	/* Store the options. */
	lq.cursor += store_options6((char *)lq.buf.data + lq.cursor,
				    sizeof(lq.buf) - lq.cursor,
				    lq.reply_opts,
				    lq.packet,
				    required_opts_lq,
				    NULL);

	/* Return our reply to the caller. */
	reply_ret->len = lq.cursor;
	reply_ret->buffer = NULL;
	if (!buffer_allocate(&reply_ret->buffer, lq.cursor, MDL)) {
		log_fatal("dhcpv6_leasequery: no memory to store Reply.");
	}
	memcpy(reply_ret->buffer->data, lq.buf.data, lq.cursor);
	reply_ret->data = reply_ret->buffer->data;

      exit:
	/* Cleanup. */
	if (lq.packet != NULL)
		packet_dereference(&lq.packet, MDL);
	if (lq.client_id.data != NULL)
		data_string_forget(&lq.client_id, MDL);
	if (lq.server_id.data != NULL)
		data_string_forget(&lq.server_id, MDL);
	if (lq.lq_query.data != NULL)
		data_string_forget(&lq.lq_query, MDL);
	if (lq.query_opts != NULL)
		option_state_dereference(&lq.query_opts, MDL);
	if (lq.reply_opts != NULL)
		option_state_dereference(&lq.reply_opts, MDL);
}
Exemplo n.º 15
0
/* Determine what, if any, forward and reverse updates need to be
 * performed, and carry them through.
 */
int
ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
	     struct iasubopt *lease6, struct iasubopt *old6,
	     struct option_state *options)
{
	unsigned long ddns_ttl = DEFAULT_DDNS_TTL;
	struct data_string ddns_hostname;
	struct data_string ddns_domainname;
	struct data_string old_ddns_fwd_name;
	struct data_string ddns_fwd_name;
	//struct data_string ddns_rev_name;
	struct data_string ddns_dhcid;
	struct binding_scope **scope = NULL;
	//struct iaddr addr;
	struct data_string d1;
	struct option_cache *oc;
	int s1, s2;
	int result = 0;
	isc_result_t rcode1 = ISC_R_SUCCESS;
	int server_updates_a = 1;
	//int server_updates_ptr = 1;
	struct buffer *bp = (struct buffer *)0;
	int ignorep = 0, client_ignorep = 0;
	int rev_name_len;
	int i;

	dhcp_ddns_cb_t *ddns_cb;
	int do_remove = 0;

	if (ddns_update_style != 2)
		return 0;

	/*
	 * sigh, I want to cancel any previous udpates before we do anything
	 * else but this means we need to deal with the lease vs lease6
	 * question twice.
	 * If there is a ddns request already outstanding cancel it.
	 */

	if (lease != NULL) {
		if ((old != NULL) && (old->ddns_cb != NULL)) {
			ddns_cancel(old->ddns_cb);
			old->ddns_cb = NULL;
		}
	} else if (lease6 != NULL) {
		if ((old6 != NULL) && (old6->ddns_cb != NULL)) {
			ddns_cancel(old->ddns_cb);
			old6->ddns_cb = NULL;
		}
	} else {
		log_fatal("Impossible condition at %s:%d.", MDL);
		/* Silence compiler warnings. */
		result = 0;
		return(0);
	}

	/* allocate our control block */
	ddns_cb = ddns_cb_alloc(MDL);
	if (ddns_cb == NULL) {
		return(0);
	}
	/* assume that we shall update both the A and ptr records */
	ddns_cb->flags = DDNS_UPDATE_ADDR | DDNS_UPDATE_PTR;
 	
	if (lease != NULL) {
		scope = &(lease->scope);
		ddns_cb->address = lease->ip_addr;
	} else if (lease6 != NULL) {
		scope = &(lease6->scope);
		memcpy(ddns_cb->address.iabuf, lease6->addr.s6_addr, 16);
		ddns_cb->address.len = 16;
	}

	memset (&d1, 0, sizeof(d1));
	memset (&ddns_hostname, 0, sizeof (ddns_hostname));
	memset (&ddns_domainname, 0, sizeof (ddns_domainname));
	memset (&old_ddns_fwd_name, 0, sizeof (ddns_fwd_name));
	memset (&ddns_fwd_name, 0, sizeof (ddns_fwd_name));
	//memset (&ddns_rev_name, 0, sizeof (ddns_rev_name));
	memset (&ddns_dhcid, 0, sizeof (ddns_dhcid));

	/* If we are allowed to accept the client's update of its own A
	   record, see if the client wants to update its own A record. */
	if (!(oc = lookup_option(&server_universe, options,
				 SV_CLIENT_UPDATES)) ||
	    evaluate_boolean_option_cache(&client_ignorep, packet, lease, NULL,
					  packet->options, options, scope,
					  oc, MDL)) {
		/* If there's no fqdn.no-client-update or if it's
		   nonzero, don't try to use the client-supplied
		   XXX */
		if (!(oc = lookup_option (&fqdn_universe, packet -> options,
					  FQDN_SERVER_UPDATE)) ||
		    evaluate_boolean_option_cache(&ignorep, packet, lease,
						  NULL, packet->options,
						  options, scope, oc, MDL))
			goto noclient;
		/* Win98 and Win2k will happily claim to be willing to
		   update an unqualified domain name. */
		if (!(oc = lookup_option (&fqdn_universe, packet -> options,
					  FQDN_DOMAINNAME)))
			goto noclient;
		if (!(oc = lookup_option (&fqdn_universe, packet -> options,
					  FQDN_FQDN)) ||
		    !evaluate_option_cache(&ddns_fwd_name, packet, lease,
					   NULL, packet->options,
					   options, scope, oc, MDL))
			goto noclient;
		ddns_cb->flags &= ~DDNS_UPDATE_ADDR;
		server_updates_a = 0;
		goto client_updates;
	}
      noclient:
	/* If do-forward-updates is disabled, this basically means don't
	   do an update unless the client is participating, so if we get
	   here and do-forward-updates is disabled, we can stop. */
	if ((oc = lookup_option (&server_universe, options,
				 SV_DO_FORWARD_UPDATES)) &&
	    !evaluate_boolean_option_cache(&ignorep, packet, lease,
					   NULL, packet->options,
					   options, scope, oc, MDL)) {
		goto out;
	}

	/* If it's a static lease, then don't do the DNS update unless we're
	   specifically configured to do so.   If the client asked to do its
	   own update and we allowed that, we don't do this test. */
	/* XXX: note that we cannot detect static DHCPv6 leases. */
	if ((lease != NULL) && (lease->flags & STATIC_LEASE)) {
		if (!(oc = lookup_option(&server_universe, options,
					 SV_UPDATE_STATIC_LEASES)) ||
		    !evaluate_boolean_option_cache(&ignorep, packet, lease,
						   NULL, packet->options,
						   options, scope, oc, MDL))
			goto out;
	}

	/*
	 * Compute the name for the A record.
	 */
	oc = lookup_option(&server_universe, options, SV_DDNS_HOST_NAME);
	if (oc)
		s1 = evaluate_option_cache(&ddns_hostname, packet, lease,
					   NULL, packet->options,
					   options, scope, oc, MDL);
	else
		s1 = 0;

	oc = lookup_option(&server_universe, options, SV_DDNS_DOMAIN_NAME);
	if (oc)
		s2 = evaluate_option_cache(&ddns_domainname, packet, lease,
					   NULL, packet->options,
					   options, scope, oc, MDL);
	else
		s2 = 0;

	if (s1 && s2) {
		if (ddns_hostname.len + ddns_domainname.len > 253) {
			log_error ("ddns_update: host.domain name too long");

			goto out;
		}

		buffer_allocate (&ddns_fwd_name.buffer,
				 ddns_hostname.len + ddns_domainname.len + 2,
				 MDL);
		if (ddns_fwd_name.buffer) {
			ddns_fwd_name.data = ddns_fwd_name.buffer->data;
			data_string_append (&ddns_fwd_name, &ddns_hostname);
			ddns_fwd_name.buffer->data[ddns_fwd_name.len] = '.';
			ddns_fwd_name.len++;
			data_string_append (&ddns_fwd_name, &ddns_domainname);
			ddns_fwd_name.buffer->data[ddns_fwd_name.len] ='\0';
			ddns_fwd_name.terminated = 1;
		}
	}
      client_updates:

	/* See if there's a name already stored on the lease. */
	if (find_bound_string(&old_ddns_fwd_name, *scope, "ddns-fwd-name")) {
		/* If there is, see if it's different. */
		if (old_ddns_fwd_name.len != ddns_fwd_name.len ||
		    memcmp (old_ddns_fwd_name.data, ddns_fwd_name.data,
			    old_ddns_fwd_name.len)) {
			/*
			 * If the name is different, mark the old record
			 * for deletion and continue getting the new info.
			 */
			do_remove = 1;
			goto in;
		}

		/* See if there's a DHCID on the lease, and if not
		 * then potentially look for 'on events' for ad-hoc ddns.
		 */
		if (!find_bound_string(&ddns_dhcid, *scope, "ddns-txt") &&
		    (old != NULL)) {
			/* If there's no DHCID, the update was probably
			   done with the old-style ad-hoc DDNS updates.
			   So if the expiry and release events look like
			   they're the same, run them.   This should delete
			   the old DDNS data. */
			if (old -> on_expiry == old -> on_release) {
				execute_statements(NULL, NULL, lease, NULL,
						   NULL, NULL, scope,
						   old->on_expiry);
				if (old -> on_expiry)
					executable_statement_dereference
						(&old -> on_expiry, MDL);
				if (old -> on_release)
					executable_statement_dereference
						(&old -> on_release, MDL);
				/* Now, install the DDNS data the new way. */
				goto in;
			}
		} else
			data_string_forget(&ddns_dhcid, MDL);

		/* See if the administrator wants to do updates even
		   in cases where the update already appears to have been
		   done. */
		if (!(oc = lookup_option(&server_universe, options,
					 SV_UPDATE_OPTIMIZATION)) ||
		    evaluate_boolean_option_cache(&ignorep, packet, lease,
						  NULL, packet->options,
						  options, scope, oc, MDL)) {
			result = 1;
			goto noerror;
		}
	/* If there's no "ddns-fwd-name" on the lease record, see if
	 * there's a ddns-client-fqdn indicating a previous client
	 * update (if it changes, we need to adjust the PTR).
	 */
	} else if (find_bound_string(&old_ddns_fwd_name, *scope,
				     "ddns-client-fqdn")) {
		/* If the name is not different, no need to update
		   the PTR record. */
		if (old_ddns_fwd_name.len == ddns_fwd_name.len &&
		    !memcmp (old_ddns_fwd_name.data, ddns_fwd_name.data,
			     old_ddns_fwd_name.len) &&
		    (!(oc = lookup_option(&server_universe, options,
					  SV_UPDATE_OPTIMIZATION)) ||
		     evaluate_boolean_option_cache(&ignorep, packet, lease,
						   NULL, packet->options,
						   options, scope, oc, MDL))) {
			goto noerror;
		}
	}
      in:
		
	/* If we don't have a name that the client has been assigned, we
	   can just skip all this. */

	if ((!ddns_fwd_name.len) || (ddns_fwd_name.len > 255)) {
		if (ddns_fwd_name.len > 255) {
			log_error ("client provided fqdn: too long");
		}

		/* If desired do the removals */
		if (do_remove != 0) {
			(void) ddns_removals(lease, lease6, NULL);
		}
		goto out;
	}

	/*
	 * Compute the RR TTL.
	 *
	 * We have two ways of computing the TTL.
	 * The old behavior was to allow for the customer to set up
	 * the option or to default things.  For v4 this was 1/2
	 * of the lease time, for v6 this was DEFAULT_DDNS_TTL.
	 * The new behavior continues to allow the customer to set
	 * up an option but the defaults are a little different.
	 * We now use 1/2 of the (preferred) lease time for both
	 * v4 and v6 and cap them at a maximum value. 
	 * If the customer chooses to use an experession that references
	 * part of the lease the v6 value will be the default as there
	 * isn't a lease available for v6.
	 */

	ddns_ttl = DEFAULT_DDNS_TTL;
	if (lease != NULL) {
		if (lease->ends <= cur_time) {
			ddns_ttl = 0;
		} else {
			ddns_ttl = (lease->ends - cur_time)/2;
		}
	}
#ifndef USE_OLD_DDNS_TTL
	else if (lease6 != NULL) {
		ddns_ttl = lease6->prefer/2;
	}

	if (ddns_ttl > MAX_DEFAULT_DDNS_TTL) {
		ddns_ttl = MAX_DEFAULT_DDNS_TTL;
	}
#endif 		

	if ((oc = lookup_option(&server_universe, options, SV_DDNS_TTL))) {
		if (evaluate_option_cache(&d1, packet, lease, NULL,
					  packet->options, options,
					  scope, oc, MDL)) {
			if (d1.len == sizeof (u_int32_t))
				ddns_ttl = getULong (d1.data);
			data_string_forget (&d1, MDL);
		}
	}

	ddns_cb->ttl = ddns_ttl;

	/*
	 * Compute the reverse IP name, starting with the domain name.
	 */
	oc = lookup_option(&server_universe, options, SV_DDNS_REV_DOMAIN_NAME);
	if (oc)
		s1 = evaluate_option_cache(&d1, packet, lease, NULL,
					   packet->options, options,
					   scope, oc, MDL);
	else
		s1 = 0;

	/* 
	 * Figure out the length of the part of the name that depends 
	 * on the address.
	 */
	if (ddns_cb->address.len == 4) {
		char buf[17];
		/* XXX: WOW this is gross. */
		rev_name_len = snprintf(buf, sizeof(buf), "%u.%u.%u.%u.",
					ddns_cb->address.iabuf[3] & 0xff,
					ddns_cb->address.iabuf[2] & 0xff,
					ddns_cb->address.iabuf[1] & 0xff,
					ddns_cb->address.iabuf[0] & 0xff) + 1;

		if (s1) {
			rev_name_len += d1.len;

			if (rev_name_len > 255) {
				log_error("ddns_update: Calculated rev domain "
					  "name too long.");
				s1 = 0;
				data_string_forget(&d1, MDL);
			}
		}
	} else if (ddns_cb->address.len == 16) {
		/* 
		 * IPv6 reverse names are always the same length, with 
		 * 32 hex characters separated by dots.
		 */
		rev_name_len = sizeof("0.1.2.3.4.5.6.7."
				      "8.9.a.b.c.d.e.f."
				      "0.1.2.3.4.5.6.7."
				      "8.9.a.b.c.d.e.f."
				      "ip6.arpa.");

		/* Set s1 to make sure we gate into updates. */
		s1 = 1;
	} else {
		log_fatal("invalid address length %d", ddns_cb->address.len);
		/* Silence compiler warnings. */
		return 0;
	}

	/* See if we are configured NOT to do reverse ptr updates */
	if ((oc = lookup_option(&server_universe, options,
				SV_DO_REVERSE_UPDATES)) &&
	    !evaluate_boolean_option_cache(&ignorep, packet, lease, NULL,
					   packet->options, options,
					   scope, oc, MDL)) {
		ddns_cb->flags &= ~DDNS_UPDATE_PTR;
	}

	if (s1) {
		buffer_allocate(&ddns_cb->rev_name.buffer, rev_name_len, MDL);
		if (ddns_cb->rev_name.buffer != NULL) {
			struct data_string *rname = &ddns_cb->rev_name;
			rname->data = rname->buffer->data;

			if (ddns_cb->address.len == 4) {
				rname->len =
				    sprintf((char *)rname->buffer->data,
					    "%u.%u.%u.%u.", 
					    ddns_cb->address.iabuf[3] & 0xff,
					    ddns_cb->address.iabuf[2] & 0xff,
					    ddns_cb->address.iabuf[1] & 0xff,
					    ddns_cb->address.iabuf[0] & 0xff);

				/*
				 * d1.data may be opaque, garbage bytes, from
				 * user (mis)configuration.
				 */
				data_string_append(rname, &d1);
				rname->buffer->data[rname->len] = '\0';
			} else if (ddns_cb->address.len == 16) {
				char *p = (char *)&rname->buffer->data;
				unsigned char *a = ddns_cb->address.iabuf + 15;
				for (i=0; i<16; i++) {
					sprintf(p, "%x.%x.", 
						(*a & 0xF), ((*a >> 4) & 0xF));
					p += 4;
					a -= 1;
				}
				strcat(p, "ip6.arpa.");
				rname->len = strlen((const char *)rname->data);
			}

			rname->terminated = 1;
		}

		if (d1.data != NULL)
			data_string_forget(&d1, MDL);
	}
Exemplo n.º 16
0
int buffer_init(buffer_t *b)
{
    return buffer_allocate(b, INITIAL_BUFFER_SIZE);
}
Exemplo n.º 17
0
ATF_TC_BODY(expire_order_reduce, tc)
{
    struct iasubopt *iaaddr1, *iaaddr2;
    struct ipv6_pool *pool;
    struct in6_addr addr;
    char *uid;
    struct data_string ds;
    struct iasubopt *expired_iaaddr;
    unsigned int attempts;

    /* set up dhcp globals */
    dhcp_context_create();

    /* and other common arguments */
    inet_pton(AF_INET6, "1:2:3:4::", &addr);

    uid = "client0";
    memset(&ds, 0, sizeof(ds));
    ds.len = strlen(uid);
    if (!buffer_allocate(&ds.buffer, ds.len, MDL)) {
        atf_tc_fail("Out of memory");
    }
    ds.data = ds.buffer->data;
    memcpy((char *)ds.data, uid, ds.len);

    pool = NULL;
    iaaddr1 = NULL;
    iaaddr2 = NULL;
    expired_iaaddr = NULL;

    /*
     * Add two leases iaaddr1 with expire time of 200
     * and iaaddr2 with expire time of 300.  Then update
     * iaaddr2 to expire in 100 instead.  This should cause
     * iaaddr2 to move with the hash list.
     */
    /* create pool and add iaaddr1 and iaaddr2 */
    if (ipv6_pool_allocate(&pool, D6O_IA_NA, &addr,
                           64, 128, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: ipv6_pool_allocate() %s:%d", MDL);
    }
    if (create_lease6(pool, &iaaddr1, &attempts, &ds, 200) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: create_lease6() %s:%d", MDL);
    }
    if (renew_lease6(pool, iaaddr1) != ISC_R_SUCCESS) {
            atf_tc_fail("ERROR: renew_lease6() %s:%d", MDL);
    }
    if (create_lease6(pool, &iaaddr2, &attempts, &ds, 300) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: create_lease6() %s:%d", MDL);
    }
    if (renew_lease6(pool, iaaddr2) != ISC_R_SUCCESS) {
            atf_tc_fail("ERROR: renew_lease6() %s:%d", MDL);
    }

    /* verify pool */
    if (pool->num_active != 2) {
        atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
    }

    /* reduce lease for iaaddr2 */
    iaaddr2->soft_lifetime_end_time = 100;
    if (renew_lease6(pool, iaaddr2) != ISC_R_SUCCESS) {
            atf_tc_fail("ERROR: renew_lease6() %s:%d", MDL);
    }

    /* expire a lease, it should be iaaddr2 with an expire time of 100 */
    if (expire_lease6(&expired_iaaddr, pool, 1000) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: expire_lease6() %s:%d", MDL);
    }
    if (expired_iaaddr == NULL) {
        atf_tc_fail("ERROR: should have expired a lease %s:%d", MDL);
    }
    if (expired_iaaddr != iaaddr2) {
        atf_tc_fail("Error: incorrect lease expired %s:%d", MDL);
    }
    if (expired_iaaddr->hard_lifetime_end_time != 100) {
        atf_tc_fail("ERROR: bad hard_lifetime_end_time %s:%d", MDL);
    }
    if (iasubopt_dereference(&expired_iaaddr, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
    }

    /* expire a lease, it should be iaaddr1 with an expire time of 200 */
    if (expire_lease6(&expired_iaaddr, pool, 1000) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: expire_lease6() %s:%d", MDL);
    }
    if (expired_iaaddr == NULL) {
        atf_tc_fail("ERROR: should have expired a lease %s:%d", MDL);
    }
    if (expired_iaaddr != iaaddr1) {
        atf_tc_fail("Error: incorrect lease expired %s:%d", MDL);
    }
    if (expired_iaaddr->hard_lifetime_end_time != 200) {
        atf_tc_fail("ERROR: bad hard_lifetime_end_time %s:%d", MDL);
    }
    if (iasubopt_dereference(&expired_iaaddr, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
    }

    /* cleanup */
    if (iasubopt_dereference(&iaaddr1, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
    }
    if (iasubopt_dereference(&iaaddr2, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
    }
    if (ipv6_pool_dereference(&pool, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: ipv6_pool_dereference() %s:%d", MDL);
    }
}
Exemplo n.º 18
0
ATF_TC_BODY(small_pool, tc)
{
    struct in6_addr addr;
    struct ipv6_pool *pool;
    struct iasubopt *iaaddr;
    char *uid;
    struct data_string ds;
    unsigned int attempts;

    /* set up dhcp globals */
    dhcp_context_create();

    /* and other common arguments */
    inet_pton(AF_INET6, "1:2:3:4::", &addr);
    addr.s6_addr[14] = 0x81;

    uid = "client0";
    memset(&ds, 0, sizeof(ds));
    ds.len = strlen(uid);
    if (!buffer_allocate(&ds.buffer, ds.len, MDL)) {
        atf_tc_fail("Out of memory");
    }
    ds.data = ds.buffer->data;
    memcpy((char *)ds.data, uid, ds.len);

    pool = NULL;
    iaaddr = NULL;

    /* tests */
    if (ipv6_pool_allocate(&pool, D6O_IA_NA, &addr,
                           127, 128, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: ipv6_pool_allocate() %s:%d", MDL);
    }

    if (create_lease6(pool, &iaaddr, &attempts,
              &ds, 42) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: create_lease6() %s:%d", MDL);
    }
    if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: renew_lease6() %s:%d", MDL);
    }
    if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
    }
    if (create_lease6(pool, &iaaddr, &attempts,
              &ds, 11) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: create_lease6() %s:%d", MDL);
    }
    if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: renew_lease6() %s:%d", MDL);
    }
    if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
    }
    if (create_lease6(pool, &iaaddr, &attempts,
              &ds, 11) != ISC_R_NORESOURCES) {
        atf_tc_fail("ERROR: create_lease6() %s:%d", MDL);
    }
    if (ipv6_pool_dereference(&pool, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: ipv6_pool_dereference() %s:%d", MDL);
    }
}
Exemplo n.º 19
0
ATF_TC_BODY(ipv6_pool_basic, tc)
{
    struct iasubopt *iaaddr;
    struct in6_addr addr;
    struct ipv6_pool *pool;
    struct ipv6_pool *pool_copy;
    char addr_buf[INET6_ADDRSTRLEN];
    char *uid;
    struct data_string ds;
    struct iasubopt *expired_iaaddr;
    unsigned int attempts;

    /* set up dhcp globals */
    dhcp_context_create();

    /* and other common arguments */
    inet_pton(AF_INET6, "1:2:3:4::", &addr);

    uid = "client0";
    memset(&ds, 0, sizeof(ds));
    ds.len = strlen(uid);
    if (!buffer_allocate(&ds.buffer, ds.len, MDL)) {
        atf_tc_fail("Out of memory");
    }
    ds.data = ds.buffer->data;
    memcpy((char *)ds.data, uid, ds.len);

    /* tests */
    /* allocate, reference */
    pool = NULL;
    if (ipv6_pool_allocate(&pool, D6O_IA_NA, &addr,
                           64, 128, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: ipv6_pool_allocate() %s:%d", MDL);
    }
    if (pool->num_active != 0) {
        atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
    }
    if (pool->bits != 64) {
        atf_tc_fail("ERROR: bad bits %s:%d", MDL);
    }
    inet_ntop(AF_INET6, &pool->start_addr, addr_buf, sizeof(addr_buf));
    if (strcmp(inet_ntop(AF_INET6, &pool->start_addr, addr_buf,
                         sizeof(addr_buf)), "1:2:3:4::") != 0) {
        atf_tc_fail("ERROR: bad start_addr %s:%d", MDL);
    }
    pool_copy = NULL;
    if (ipv6_pool_reference(&pool_copy, pool, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: ipv6_pool_reference() %s:%d", MDL);
    }

    /* create_lease6, renew_lease6, expire_lease6 */
    iaaddr = NULL;
    if (create_lease6(pool, &iaaddr,
                      &attempts, &ds, 1) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: create_lease6() %s:%d", MDL);
    }
    if (pool->num_inactive != 1) {
        atf_tc_fail("ERROR: bad num_inactive %s:%d", MDL);
    }
    if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: renew_lease6() %s:%d", MDL);
    }
    if (pool->num_active != 1) {
        atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
    }
    expired_iaaddr = NULL;
    if (expire_lease6(&expired_iaaddr, pool, 0) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: expire_lease6() %s:%d", MDL);
    }
    if (expired_iaaddr != NULL) {
        atf_tc_fail("ERROR: should not have expired a lease %s:%d", MDL);
    }
    if (pool->num_active != 1) {
        atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
    }
    if (expire_lease6(&expired_iaaddr, pool, 1000) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: expire_lease6() %s:%d", MDL);
    }
    if (expired_iaaddr == NULL) {
        atf_tc_fail("ERROR: should have expired a lease %s:%d", MDL);
    }
    if (iasubopt_dereference(&expired_iaaddr, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
    }
    if (pool->num_active != 0) {
        atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
    }
    if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
    }

    /* release_lease6, decline_lease6 */
    if (create_lease6(pool, &iaaddr, &attempts,
              &ds, 1) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: create_lease6() %s:%d", MDL);
    }
    if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: renew_lease6() %s:%d", MDL);
    }
    if (pool->num_active != 1) {
        atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
    }
    if (release_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: decline_lease6() %s:%d", MDL);
    }
    if (pool->num_active != 0) {
        atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
    }
    if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
    }
    if (create_lease6(pool, &iaaddr, &attempts,
              &ds, 1) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: create_lease6() %s:%d", MDL);
    }
    if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: renew_lease6() %s:%d", MDL);
    }
    if (pool->num_active != 1) {
        atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
    }
    if (decline_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: decline_lease6() %s:%d", MDL);
    }
    if (pool->num_active != 1) {
        atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
    }
    if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
    }

    /* dereference */
    if (ipv6_pool_dereference(&pool, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: ipv6_pool_reference() %s:%d", MDL);
    }
    if (ipv6_pool_dereference(&pool_copy, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: ipv6_pool_reference() %s:%d", MDL);
    }
}
Exemplo n.º 20
0
ATF_TC_BODY(expire_order, tc)
{
    struct iasubopt *iaaddr;
    struct ipv6_pool *pool;
    struct in6_addr addr;
        int i;
    char *uid;
    struct data_string ds;
    struct iasubopt *expired_iaaddr;
    unsigned int attempts;

    /* set up dhcp globals */
    dhcp_context_create();

    /* and other common arguments */
    inet_pton(AF_INET6, "1:2:3:4::", &addr);

    uid = "client0";
    memset(&ds, 0, sizeof(ds));
    ds.len = strlen(uid);
    if (!buffer_allocate(&ds.buffer, ds.len, MDL)) {
        atf_tc_fail("Out of memory");
    }
    ds.data = ds.buffer->data;
    memcpy((char *)ds.data, uid, ds.len);

    iaaddr = NULL;
    expired_iaaddr = NULL;

    /* tests */
    pool = NULL;
    if (ipv6_pool_allocate(&pool, D6O_IA_NA, &addr,
                           64, 128, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: ipv6_pool_allocate() %s:%d", MDL);
    }

    for (i=10; i<100; i+=10) {
        if (create_lease6(pool, &iaaddr, &attempts,
                  &ds, i) != ISC_R_SUCCESS) {
            atf_tc_fail("ERROR: create_lease6() %s:%d", MDL);
                }
        if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
            atf_tc_fail("ERROR: renew_lease6() %s:%d", MDL);
                }
        if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
            atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
                }
        if (pool->num_active != (i / 10)) {
            atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
                }
    }
    if (pool->num_active != 9) {
        atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
    }

    for (i=10; i<100; i+=10) {
        if (expire_lease6(&expired_iaaddr,
                  pool, 1000) != ISC_R_SUCCESS) {
            atf_tc_fail("ERROR: expire_lease6() %s:%d", MDL);
                }
        if (expired_iaaddr == NULL) {
            atf_tc_fail("ERROR: should have expired a lease %s:%d",
                   MDL);
                }
        if (pool->num_active != (9 - (i / 10))) {
            atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
                }
        if (expired_iaaddr->hard_lifetime_end_time != i) {
            atf_tc_fail("ERROR: bad hard_lifetime_end_time %s:%d",
                   MDL);
                }
        if (iasubopt_dereference(&expired_iaaddr, MDL) !=
                ISC_R_SUCCESS) {
            atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
                }
    }
    if (pool->num_active != 0) {
        atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
    }
    expired_iaaddr = NULL;
    if (expire_lease6(&expired_iaaddr, pool, 1000) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: expire_lease6() %s:%d", MDL);
    }
    if (ipv6_pool_dereference(&pool, MDL) != ISC_R_SUCCESS) {
        atf_tc_fail("ERROR: ipv6_pool_dereference() %s:%d", MDL);
    }
}
Exemplo n.º 21
0
int buffer_init_contents(buffer_t *b, const char *data, size_t size)
{
    buffer_allocate(b, size);
    return buffer_set(b, data, size);
}
Exemplo n.º 22
0
eDnsStatus dnscache_lookup (dnscache_t *dnscache, const char *dname, int type, size_t max_hosts, off_t *index, time_t current_time)
{
	dnscache_entry_t *record;
	rr_t *rr_list;
	buffer_t name;
	unsigned int position;
	int min_ttl;
	int lookup;
	size_t len;
	size_t i;

	if (max_hosts > MAX_HOSTS) {
		return DNS_ERROR;
	}

	if (search (dnscache, dname, type, &position) < 0) {
		/* DNS cache miss. */
		buffer_init (&name, 64);
		len = strlen (dname);
		if (buffer_allocate (&name, len + 1) < 0) {
			buffer_free (&name);
			return DNS_ERROR;
		}

		memcpy (name.data, dname, len + 1);
		name.used = len + 1;

		if (allocate (dnscache) < 0) {
			buffer_free (&name);
			return DNS_ERROR;
		}

		/* We might have emptied the cache. */
		if (dnscache->used == 0) {
			position = 0;
		}

		record = &(dnscache->records[dnscache->used]);

		memcpy (&record->name, &name, sizeof (buffer_t));
		record->type = type;
		record->timestamp = current_time;
		rr_list_init (record->rr_list, MAX_HOSTS);
		record->nhosts = 0;

		record->status = dns_lookup (dname, type, max_hosts, record->rr_list, &record->nhosts);

		*index = dnscache->used;

		if (position < dnscache->used) {
			memmove (&(dnscache->index[position + 1]), &(dnscache->index[position]), (dnscache->used - position) * sizeof (off_t));
		}

		dnscache->index[position] = dnscache->used++;

		return record->status;
	}

	*index = dnscache->index[position];
	record = &(dnscache->records[*index]);
	rr_list = record->rr_list;

	if ((record->status == DNS_HOST_NOT_FOUND) || (record->status == DNS_NO_DATA)) {
		if (record->timestamp + QUERY_MIN_INTERVAL >= current_time) {
			return record->status;
		}

		lookup = 1;
	} else if (record->status != DNS_SUCCESS) {
		lookup = 1;
	} else {
		/* Compute the minimum TTL. */
		min_ttl = rr_list[0].ttl;
		for (i = 1; i < record->nhosts; i++) {
			if (rr_list[i].ttl < min_ttl) {
				min_ttl = rr_list[i].ttl;
			}
		}

		/* If the TTL has already expired... */
		if (record->timestamp + min_ttl < current_time) {
			lookup = 1;
		} else {
			lookup = 0;
		}
	}

	if (lookup) {
		rr_list_free (rr_list, MAX_HOSTS);

		record->status = dns_lookup (dname, type, max_hosts, rr_list, &record->nhosts);
		record->timestamp = current_time;
	}

	return record->status;
}
Exemplo n.º 23
0
static VALUE
buffer_alloc_inout(int argc, VALUE* argv, VALUE klass)
{
    return buffer_initialize(argc, argv, buffer_allocate(klass));
}
Exemplo n.º 24
0
/*
 * Process a by-address lease query.
 */
static int
process_lq_by_address(struct lq6_state *lq) {
	struct packet *packet = lq->packet;
	struct option_cache *oc;
	struct ipv6_pool *pool = NULL;
	struct data_string data;
	struct in6_addr addr;
	struct iasubopt *iaaddr = NULL;
	struct option_state *opt_state = NULL;
	u_int32_t lifetime;
	unsigned opt_cursor;
	int ret_val = 0;

	/*
	 * Get the IAADDR.
	 */
	oc = lookup_option(&dhcpv6_universe, lq->query_opts, D6O_IAADDR);
	if (oc == NULL) {
		if (!set_error(lq, STATUS_MalformedQuery,
			       "No OPTION_IAADDR.")) {
			log_error("process_lq_by_address: unable "
				  "to set MalformedQuery status code.");
			return 0;
		}
		return 1;
	}
	memset(&data, 0, sizeof(data));
	if (!evaluate_option_cache(&data, packet,
				   NULL, NULL,
				   lq->query_opts, NULL,
				   &global_scope, oc, MDL) ||
	    (data.len < IAADDR_OFFSET)) {
		log_error("process_lq_by_address: error evaluating IAADDR.");
		goto exit;
	}
	memcpy(&addr, data.data, sizeof(addr));
	data_string_forget(&data, MDL);

	/*
	 * Find the lease.
	 * Note the RFC 5007 says to use the link-address to find the link
	 * or the ia-aadr when it is :: but in any case the ia-addr has
	 * to be on the link, so we ignore the link-address here.
	 */
	if (find_ipv6_pool(&pool, D6O_IA_NA, &addr) != ISC_R_SUCCESS) {
		if (!set_error(lq, STATUS_NotConfigured,
			       "Address not in a pool.")) {
			log_error("process_lq_by_address: unable "
				  "to set NotConfigured status code.");
			goto exit;
		}
		ret_val = 1;
		goto exit;
	}
	if (iasubopt_hash_lookup(&iaaddr, pool->leases, &addr,
				 sizeof(addr), MDL) == 0) {
		ret_val = 1;
		goto exit;
	}
	if ((iaaddr == NULL) || (iaaddr->state != FTS_ACTIVE) ||
	    (iaaddr->ia == NULL) || (iaaddr->ia->iaid_duid.len <= 4)) {
		ret_val = 1;
		goto exit;
	}

	/*
	 * Build the client-data option (with client-id, ia-addr and clt-time).
	 */
	if (!option_state_allocate(&opt_state, MDL)) {
		log_error("process_lq_by_address: "
			  "no memory for option state.");
		goto exit;
	}

	data_string_copy(&data, &iaaddr->ia->iaid_duid, MDL);
	data.data += 4;
	data.len -= 4;
	if (!save_option_buffer(&dhcpv6_universe, opt_state,
				NULL, (unsigned char *)data.data, data.len,
				D6O_CLIENTID, 0)) {
		log_error("process_lq_by_address: error saving client ID.");
		goto exit;
	}
	data_string_forget(&data, MDL);

	data.len = IAADDR_OFFSET;
	if (!buffer_allocate(&data.buffer, data.len, MDL)) {
		log_error("process_lq_by_address: no memory for ia-addr.");
		goto exit;
	}
	data.data = data.buffer->data;
	memcpy(data.buffer->data, &iaaddr->addr, 16);
	lifetime = iaaddr->prefer;
	putULong(data.buffer->data + 16, lifetime);
	lifetime = iaaddr->valid;
	putULong(data.buffer->data + 20, lifetime);
	if (!save_option_buffer(&dhcpv6_universe, opt_state,
				NULL, (unsigned char *)data.data, data.len,
				D6O_IAADDR, 0)) {
		log_error("process_lq_by_address: error saving ia-addr.");
		goto exit;
	}
	data_string_forget(&data, MDL);

	lifetime = htonl(iaaddr->ia->cltt);
	if (!save_option_buffer(&dhcpv6_universe, opt_state,
				NULL, (unsigned char *)&lifetime, 4,
				D6O_CLT_TIME, 0)) {
		log_error("process_lq_by_address: error saving clt time.");
		goto exit;
	}

	/*
	 * Store the client-data option.
	 */
	opt_cursor = lq->cursor;
	putUShort(lq->buf.data + lq->cursor, (unsigned)D6O_CLIENT_DATA);
	lq->cursor += 2;
	/* Skip option length. */
	lq->cursor += 2;

	lq->cursor += store_options6((char *)lq->buf.data + lq->cursor,
				     sizeof(lq->buf) - lq->cursor,
				     opt_state, lq->packet,
				     required_opt_CLIENT_DATA, NULL);
	/* Reset the length. */
	putUShort(lq->buf.data + opt_cursor + 2,
		  lq->cursor - (opt_cursor + 4));

	/* Done. */
	ret_val = 1;

     exit:
	if (data.data != NULL)
		data_string_forget(&data, MDL);
	if (pool != NULL)
		ipv6_pool_dereference(&pool, MDL);
	if (iaaddr != NULL)
		iasubopt_dereference(&iaaddr, MDL);
	if (opt_state != NULL)
		option_state_dereference(&opt_state, MDL);
	return ret_val;
}
Exemplo n.º 25
0
ATF_TC_BODY(buffer_dereference, tc) {
    struct buffer *a, *b;

    /**
     * Confirm buffer_dereference() doesn't work if we pass in NULL.
     *
     * TODO: we should confirm we get an error message here.
     */
    if (buffer_dereference(NULL, MDL)) {
        atf_tc_fail("succeeded on an error input");
    }

    /**
     * Confirm buffer_dereference() doesn't work if we pass in
     * a pointer to NULL.
     *
     * @TODO: we should confirm we get an error message here.
     */
    a = NULL;
    if (buffer_dereference(&a, MDL)) {
        atf_tc_fail("succeeded on an error input");
    }

    /*
     * Confirm we work under normal circumstances.
     */
    a = NULL;
    if (!buffer_allocate(&a, 100, MDL)) {
        atf_tc_fail("failed on allocate");
    }
    if (!buffer_dereference(&a, MDL)) {
        atf_tc_fail("buffer_dereference() failed");
    }
    if (a != NULL) {
        atf_tc_fail("non-null buffer after buffer_dereference()");
    }

    /**
     * Confirm we get an error from negative refcnt.
     *
     * @TODO: we should confirm we get an error message here.
     */
    a = NULL;
    if (!buffer_allocate(&a, 100, MDL)) {
        atf_tc_fail("failed on allocate");
    }
    b = NULL;
    if (!buffer_reference(&b, a, MDL)) {
        atf_tc_fail("buffer_reference() failed");
    }
    a->refcnt = 0;    /* purposely set to invalid value */
    if (buffer_dereference(&a, MDL)) {
        atf_tc_fail("buffer_dereference() succeeded on error input");
    }
    a->refcnt = 2;
    if (!buffer_dereference(&b, MDL)) {
        atf_tc_fail("buffer_dereference() failed");
    }
    if (!buffer_dereference(&a, MDL)) {
        atf_tc_fail("buffer_dereference() failed");
    }
}
Exemplo n.º 26
0
int ddns_updates (struct packet *packet,
		  struct lease *lease, struct lease *old,
		  struct lease_state *state)
{
	unsigned long ddns_ttl = DEFAULT_DDNS_TTL;
	struct data_string ddns_hostname;
	struct data_string ddns_domainname;
	struct data_string old_ddns_fwd_name;
	struct data_string ddns_fwd_name;
	struct data_string ddns_rev_name;
	struct data_string ddns_dhcid;
	unsigned len;
	struct data_string d1;
	struct option_cache *oc;
	int s1, s2;
	int result = 0;
	isc_result_t rcode1 = ISC_R_SUCCESS, rcode2 = ISC_R_SUCCESS;
	int server_updates_a = 1;
	int server_updates_ptr = 1;
	struct buffer *bp = (struct buffer *)0;
	int ignorep = 0, client_ignorep = 0;

	if (ddns_update_style != 2)
		return 0;

	/* Can only cope with IPv4 addrs at the moment. */
	if (lease -> ip_addr . len != 4)
		return 0;

	memset(&d1, 0, sizeof(d1));
	memset (&ddns_hostname, 0, sizeof (ddns_hostname));
	memset (&ddns_domainname, 0, sizeof (ddns_domainname));
	memset (&old_ddns_fwd_name, 0, sizeof (ddns_fwd_name));
	memset (&ddns_fwd_name, 0, sizeof (ddns_fwd_name));
	memset (&ddns_rev_name, 0, sizeof (ddns_rev_name));
	memset (&ddns_dhcid, 0, sizeof (ddns_dhcid));

	/* If we are allowed to accept the client's update of its own A
	   record, see if the client wants to update its own A record. */
	if (!(oc = lookup_option(&server_universe, state->options,
				 SV_CLIENT_UPDATES)) ||
	    evaluate_boolean_option_cache(&client_ignorep, packet, lease, NULL,
					  packet->options, state->options,
					  &lease->scope, oc, MDL)) {
		/* If there's no fqdn.no-client-update or if it's
		   nonzero, don't try to use the client-supplied
		   XXX */
		if (!(oc = lookup_option (&fqdn_universe, packet -> options,
					  FQDN_SERVER_UPDATE)) ||
		    evaluate_boolean_option_cache (&ignorep, packet, lease,
						   (struct client_state *)0,
						   packet -> options,
						   state -> options,
						   &lease -> scope, oc, MDL))
			goto noclient;
		/* Win98 and Win2k will happily claim to be willing to
		   update an unqualified domain name. */
		if (!(oc = lookup_option (&fqdn_universe, packet -> options,
					  FQDN_DOMAINNAME)))
			goto noclient;
		if (!(oc = lookup_option (&fqdn_universe, packet -> options,
					  FQDN_FQDN)) ||
		    !evaluate_option_cache (&ddns_fwd_name, packet, lease,
					    (struct client_state *)0,
					    packet -> options,
					    state -> options,
					    &lease -> scope, oc, MDL))
			goto noclient;
		server_updates_a = 0;
		goto client_updates;
	}
      noclient:
	/* If do-forward-updates is disabled, this basically means don't
	   do an update unless the client is participating, so if we get
	   here and do-forward-updates is disabled, we can stop. */
	if ((oc = lookup_option (&server_universe, state -> options,
				 SV_DO_FORWARD_UPDATES)) &&
	    !evaluate_boolean_option_cache (&ignorep, packet, lease,
					    (struct client_state *)0,
					    packet -> options,
					    state -> options,
					    &lease -> scope, oc, MDL)) {
		return 0;
	}

	/* If it's a static lease, then don't do the DNS update unless we're
	   specifically configured to do so.   If the client asked to do its
	   own update and we allowed that, we don't do this test. */
	if (lease -> flags & STATIC_LEASE) {
		if (!(oc = lookup_option (&server_universe, state -> options,
					  SV_UPDATE_STATIC_LEASES)) ||
		    !evaluate_boolean_option_cache (&ignorep, packet, lease,
						    (struct client_state *)0,
						    packet -> options,
						    state -> options,
						    &lease -> scope, oc, MDL))
			return 0;
	}

	/*
	 * Compute the name for the A record.
	 */
	oc = lookup_option (&server_universe, state -> options,
			    SV_DDNS_HOST_NAME);
	if (oc)
		s1 = evaluate_option_cache (&ddns_hostname, packet, lease,
					    (struct client_state *)0,
					    packet -> options,
					    state -> options,
					    &lease -> scope, oc, MDL);
	else
		s1 = 0;

	oc = lookup_option (&server_universe, state -> options,
			    SV_DDNS_DOMAIN_NAME);
	if (oc)
		s2 = evaluate_option_cache (&ddns_domainname, packet, lease,
					    (struct client_state *)0,
					    packet -> options,
					    state -> options,
					    &lease -> scope, oc, MDL);
	else
		s2 = 0;

	if (s1 && s2) {
		if (ddns_hostname.len + ddns_domainname.len > 253) {
			log_error ("ddns_update: host.domain name too long");

			goto out;
		}

		buffer_allocate (&ddns_fwd_name.buffer,
				 ddns_hostname.len + ddns_domainname.len + 2,
				 MDL);
		if (ddns_fwd_name.buffer) {
			ddns_fwd_name.data = ddns_fwd_name.buffer -> data;
			data_string_append (&ddns_fwd_name, &ddns_hostname);
			ddns_fwd_name.buffer -> data [ddns_fwd_name.len] = '.';
			ddns_fwd_name.len++;
			data_string_append (&ddns_fwd_name, &ddns_domainname);
			ddns_fwd_name.buffer -> data [ddns_fwd_name.len] ='\0';
			ddns_fwd_name.terminated = 1;
		}
	}
      client_updates:

	/* See if there's a name already stored on the lease. */
	if (find_bound_string (&old_ddns_fwd_name,
			       lease -> scope, "ddns-fwd-name")) {
		/* If there is, see if it's different. */
		if (old_ddns_fwd_name.len != ddns_fwd_name.len ||
		    memcmp (old_ddns_fwd_name.data, ddns_fwd_name.data,
			    old_ddns_fwd_name.len)) {
			/* If the name is different, try to delete
			   the old A record. */
			if (!ddns_removals (lease))
				goto out;
			/* If the delete succeeded, go install the new
			   record. */
			goto in;
		}

		/* See if there's a DHCID on the lease. */
		if (!find_bound_string (&ddns_dhcid,
					lease -> scope, "ddns-txt")) {
			/* If there's no DHCID, the update was probably
			   done with the old-style ad-hoc DDNS updates.
			   So if the expiry and release events look like
			   they're the same, run them.   This should delete
			   the old DDNS data. */
			if (old -> on_expiry == old -> on_release) {
				execute_statements ((struct binding_value **)0,
						    (struct packet *)0, lease,
						    (struct client_state *)0,
						    (struct option_state *)0,
						    (struct option_state *)0,
						    &lease -> scope,
						    old -> on_expiry);
				if (old -> on_expiry)
					executable_statement_dereference
						(&old -> on_expiry, MDL);
				if (old -> on_release)
					executable_statement_dereference
						(&old -> on_release, MDL);
				/* Now, install the DDNS data the new way. */
				goto in;
			}
		} else
			data_string_forget(&ddns_dhcid, MDL);

		/* See if the administrator wants to do updates even
		   in cases where the update already appears to have been
		   done. */
		if (!(oc = lookup_option (&server_universe, state -> options,
					  SV_UPDATE_OPTIMIZATION)) ||
		    evaluate_boolean_option_cache (&ignorep, packet, lease,
						   (struct client_state *)0,
						   packet -> options,
						   state -> options,
						   &lease -> scope, oc, MDL)) {
			result = 1;
			goto noerror;
		}
	/* If there's no "ddns-fwd-name" on the lease record, see if
	 * there's a ddns-client-fqdn indicating a previous client
	 * update (if it changes, we need to adjust the PTR).
	 */
	} else if (find_bound_string(&old_ddns_fwd_name, lease->scope,
				     "ddns-client-fqdn")) {
		/* If the name is not different, no need to update
		   the PTR record. */
		if (old_ddns_fwd_name.len == ddns_fwd_name.len &&
		    !memcmp (old_ddns_fwd_name.data, ddns_fwd_name.data,
			     old_ddns_fwd_name.len) &&
		    (!(oc = lookup_option (&server_universe,
					   state -> options,
					   SV_UPDATE_OPTIMIZATION)) ||
		     evaluate_boolean_option_cache (&ignorep, packet, lease,
						    (struct client_state *)0,
						    packet -> options,
						    state -> options,
						    &lease -> scope, oc,
						    MDL))) {
			goto noerror;
		}
	}
      in:
		
	/* If we don't have a name that the client has been assigned, we
	   can just skip all this. */
	if (!ddns_fwd_name.len)
		goto out;

	if (ddns_fwd_name.len > 255) {
		log_error ("client provided fqdn: too long");
		goto out;
	}

	/*
	 * Compute the RR TTL.
	 */
	ddns_ttl = DEFAULT_DDNS_TTL;
	if ((oc = lookup_option (&server_universe, state -> options,
				 SV_DDNS_TTL))) {
		if (evaluate_option_cache (&d1, packet, lease,
					   (struct client_state *)0,
					   packet -> options,
					   state -> options,
					   &lease -> scope, oc, MDL)) {
			if (d1.len == sizeof (u_int32_t))
				ddns_ttl = getULong (d1.data);
			data_string_forget (&d1, MDL);
		}
	}

	/* CC: see if we are configured NOT to do reverse ptr updates
        */
	if ((oc = lookup_option (&server_universe, state -> options,
				 SV_DO_REVERSE_UPDATES)) &&
	    !evaluate_boolean_option_cache (&ignorep, packet, lease,
					    (struct client_state *)0,
					    packet -> options,
					    state -> options,
					    &lease -> scope, oc, MDL)) {
		server_updates_ptr = 0;
	}

	/*
	 * Compute the reverse IP name.
	 */
	oc = lookup_option (&server_universe, state -> options,
			    SV_DDNS_REV_DOMAIN_NAME);
	if (oc)
		s1 = evaluate_option_cache (&d1, packet, lease,
					    (struct client_state *)0,
					    packet -> options,
					    state -> options,
					    &lease -> scope, oc, MDL);
	else
		s1 = 0;

	if (s1 && (d1.len > 238)) {
		log_error ("ddns_update: Calculated rev domain name too long.");
		s1 = 0;
		data_string_forget (&d1, MDL);
	}

	if (oc && s1) {
		/* Buffer length:
		   XXX.XXX.XXX.XXX.<ddns-rev-domain-name>\0 */
		buffer_allocate (&ddns_rev_name.buffer,
				 d1.len + 17, MDL);
		if (ddns_rev_name.buffer) {
			ddns_rev_name.data = ddns_rev_name.buffer -> data;

			/* %Audit% Cannot exceed 17 bytes. %2004.06.17,Safe% */
			sprintf ((char *)ddns_rev_name.buffer -> data,
				  "%u.%u.%u.%u.",
				  lease -> ip_addr . iabuf[3] & 0xff,
				  lease -> ip_addr . iabuf[2] & 0xff,
				  lease -> ip_addr . iabuf[1] & 0xff,
				  lease -> ip_addr . iabuf[0] & 0xff);

			ddns_rev_name.len =
				strlen ((const char *)ddns_rev_name.data);
			data_string_append (&ddns_rev_name, &d1);
			ddns_rev_name.buffer -> data [ddns_rev_name.len] ='\0';
			ddns_rev_name.terminated = 1;
		}
		
		data_string_forget (&d1, MDL);
	}

	/*
	 * If we are updating the A record, compute the DHCID value.
	 */
	if (server_updates_a) {
		if (lease -> uid && lease -> uid_len)
			result = get_dhcid (&ddns_dhcid,
					    DHO_DHCP_CLIENT_IDENTIFIER,
					    lease -> uid, lease -> uid_len);
		else
			result = get_dhcid (&ddns_dhcid, 0,
					    lease -> hardware_addr.hbuf,
					    lease -> hardware_addr.hlen);
		if (!result)
			goto badfqdn;
	}

	/*
	 * Start the resolver, if necessary.
	 */
	if (!resolver_inited) {
		minires_ninit (&resolver_state);
		resolver_inited = 1;
		resolver_state.retrans = 1;
		resolver_state.retry = 1;
	}

	/*
	 * Perform updates.
	 */
	if (ddns_fwd_name.len && ddns_dhcid.len) {
		unsigned conflict;

		oc = lookup_option(&server_universe, state->options,
				   SV_DDNS_CONFLICT_DETECT);
		if (!oc ||
		    evaluate_boolean_option_cache(&ignorep, packet, lease,
						  NULL, packet->options,
						  state->options,
						  &lease->scope, oc, MDL))
			conflict = 1;
		else
			conflict = 0;

		rcode1 = ddns_update_a (&ddns_fwd_name, lease -> ip_addr,
					&ddns_dhcid, ddns_ttl, 0, conflict);
	}

	if (rcode1 == ISC_R_SUCCESS && server_updates_ptr) {
		if (ddns_fwd_name.len && ddns_rev_name.len)
			rcode2 = ddns_update_ptr (&ddns_fwd_name,
						  &ddns_rev_name, ddns_ttl);
	} else
		rcode2 = rcode1;

	if (rcode1 == ISC_R_SUCCESS &&
	    (server_updates_a || rcode2 == ISC_R_SUCCESS)) {
		bind_ds_value (&lease -> scope, 
			       (server_updates_a
				? "ddns-fwd-name" : "ddns-client-fqdn"),
			       &ddns_fwd_name);
		if (server_updates_a)
			bind_ds_value (&lease -> scope, "ddns-txt",
				       &ddns_dhcid);
	}

	if (rcode2 == ISC_R_SUCCESS && server_updates_ptr) {
		bind_ds_value (&lease -> scope, "ddns-rev-name",
			       &ddns_rev_name);
	}

      noerror:
	/*
	 * If fqdn-reply option is disabled in dhcpd.conf, then don't
	 * send the client an FQDN option at all, even if one was requested.
	 * (WinXP clients allegedly misbehave if the option is present,
	 * refusing to handle PTR updates themselves).
	 */
	if ((oc = lookup_option (&server_universe, state->options,
  				 SV_FQDN_REPLY)) &&
  	    !evaluate_boolean_option_cache (&ignorep, packet, lease,
  					    (struct client_state *)0,
  					    packet->options,
  					    state->options,
  					    &lease->scope, oc, MDL)) {
  	    	goto badfqdn;

	/* If we're ignoring client updates, then we tell a sort of 'white
	 * lie'.  We've already updated the name the server wants (per the
	 * config written by the server admin).  Now let the client do as
	 * it pleases with the name they supplied (if any).
	 *
	 * We only form an FQDN option this way if the client supplied an
	 * FQDN option that had FQDN_SERVER_UPDATE set false.
	 */
	} else if (client_ignorep &&
	    (oc = lookup_option(&fqdn_universe, packet->options,
				FQDN_SERVER_UPDATE)) &&
	    !evaluate_boolean_option_cache(&ignorep, packet, lease, NULL,
					   packet->options, state->options,
					   &lease->scope, oc, MDL)) {
		oc = lookup_option(&fqdn_universe, packet->options, FQDN_FQDN);
		if (oc && evaluate_option_cache(&d1, packet, lease, NULL,
						packet->options, state->options,
						&global_scope, oc, MDL)) {
			if (d1.len == 0 ||
			    !buffer_allocate(&bp, d1.len + 5, MDL))
				goto badfqdn;

			/* Server pretends it is not updating. */
			bp->data[0] = 0;
			if (!save_option_buffer(&fqdn_universe, state->options,
						bp, &bp->data[0], 1,
						FQDN_SERVER_UPDATE, 0))
				goto badfqdn;

			/* Client is encouraged to update. */
			bp->data[1] = 0;
			if (!save_option_buffer(&fqdn_universe, state->options,
						bp, &bp->data[1], 1,
						FQDN_NO_CLIENT_UPDATE, 0))
				goto badfqdn;

			/* Use the encoding of client's FQDN option. */
			oc = lookup_option(&fqdn_universe, packet->options,
					   FQDN_ENCODED);
			if (oc && evaluate_boolean_option_cache(&ignorep,
							packet, lease, NULL,
							packet->options,
							state->options,
							&lease->scope, oc,
							MDL))
				bp->data[2] = 1; /* FQDN is encoded. */
			else
				bp->data[2] = 0; /* FQDN is not encoded. */

			if (!save_option_buffer(&fqdn_universe, state->options,
						bp, &bp->data[2], 1,
						FQDN_ENCODED, 0))
				goto badfqdn;

			/* Current FQDN drafts indicate 255 is mandatory. */
			bp->data[3] = 255;
			if (!save_option_buffer(&fqdn_universe, state->options,
						bp, &bp->data[3], 1,
						FQDN_RCODE1, 0))
				goto badfqdn;

			bp->data[4] = 255;
			if (!save_option_buffer(&fqdn_universe, state->options,
						bp, &bp->data[4], 1,
						FQDN_RCODE2, 0))
				goto badfqdn;

			/* Copy in the FQDN supplied by the client.  Note well
			 * that the format of this option in the cache is going
			 * to be in text format.  If the fqdn supplied by the
			 * client is encoded, it is decoded into the option
			 * cache when parsed out of the packet.  It will be
			 * re-encoded when the option is assembled to be
			 * transmitted if the client elects that encoding.
			 */
			memcpy(&bp->data[5], d1.data, d1.len);
			if (!save_option_buffer(&fqdn_universe, state->options,
						bp, &bp->data[5], 1,
						FQDN_FQDN, 0))
				goto badfqdn;

			data_string_forget(&d1, MDL);
		}
	/* Set up the outgoing FQDN option if there was an incoming
	 * FQDN option.  If there's a valid FQDN option, there MUST
	 * be an FQDN_SERVER_UPDATES suboption, it's part of the fixed
	 * length head of the option contents, so we test the latter
	 * to detect the presence of the former.
	 */
	} else if ((oc = lookup_option(&fqdn_universe, packet->options,
				       FQDN_ENCODED)) &&
		   buffer_allocate(&bp, ddns_fwd_name.len + 5, MDL)) {
		bp -> data [0] = server_updates_a;
		if (!save_option_buffer (&fqdn_universe, state -> options,
					 bp, &bp -> data [0], 1,
					 FQDN_SERVER_UPDATE, 0))
			goto badfqdn;
		bp -> data [1] = server_updates_a;
		if (!save_option_buffer (&fqdn_universe, state -> options,
					 bp, &bp -> data [1], 1,
					 FQDN_NO_CLIENT_UPDATE, 0))
			goto badfqdn;

		/* Do the same encoding the client did. */
		if (evaluate_boolean_option_cache(&ignorep, packet, lease,
						  NULL, packet->options,
						  state->options,
						  &lease->scope, oc, MDL))
			bp -> data [2] = 1;
		else
			bp -> data [2] = 0;
		if (!save_option_buffer (&fqdn_universe, state -> options,
					 bp, &bp -> data [2], 1,
					 FQDN_ENCODED, 0))
			goto badfqdn;
		bp -> data [3] = isc_rcode_to_ns (rcode1);
		if (!save_option_buffer (&fqdn_universe, state -> options,
					 bp, &bp -> data [3], 1,
					 FQDN_RCODE1, 0))
			goto badfqdn;
		bp -> data [4] = isc_rcode_to_ns (rcode2);
		if (!save_option_buffer (&fqdn_universe, state -> options,
					 bp, &bp -> data [4], 1,
					 FQDN_RCODE2, 0))
			goto badfqdn;
		if (ddns_fwd_name.len) {
		    memcpy (&bp -> data [5],
			    ddns_fwd_name.data, ddns_fwd_name.len);
		    if (!save_option_buffer (&fqdn_universe, state -> options,
					     bp, &bp -> data [5],
					     ddns_fwd_name.len,
					     FQDN_FQDN, 0))
			goto badfqdn;
		}
	}

      badfqdn:
      out:
	/*
	 * Final cleanup.
	 */
	data_string_forget(&d1, MDL);
	data_string_forget(&ddns_hostname, MDL);
	data_string_forget(&ddns_domainname, MDL);
	data_string_forget(&old_ddns_fwd_name, MDL);
	data_string_forget(&ddns_fwd_name, MDL);
	data_string_forget(&ddns_rev_name, MDL);
	data_string_forget(&ddns_dhcid, MDL);
	if (bp)
		buffer_dereference(&bp, MDL);

	return result;
}
Exemplo n.º 27
0
/// @brief executes uid hash test for specified client-ids (3 hosts)
///
/// Creates three host structures, adds first host to the uid hash,
/// then adds second host to the hash, then removes first host,
/// then removed the second. Many checks are performed during all
/// operations.
///
/// @param clientid1 client-id of the first host
/// @param clientid1_len client-id1 length (may be 0 for strings)
/// @param clientid2 client-id of the second host
/// @param clientid2_len client-id2 length (may be 0 for strings)
/// @param clientid3 client-id of the second host
/// @param clientid3_len client-id2 length (may be 0 for strings)
void lease_hash_test_3hosts(unsigned char clientid1[], size_t clientid1_len,
                            unsigned char clientid2[], size_t clientid2_len,
                            unsigned char clientid3[], size_t clientid3_len) {

    printf("Checking hash operation for 3 hosts: clientid1-len=%lu"
           " clientid2-len=%lu clientid3-len=%lu\n",
           (unsigned long) clientid1_len, (unsigned long) clientid2_len,
           (unsigned long) clientid3_len);

    dhcp_db_objects_setup ();
    dhcp_common_objects_setup ();

    /* check that there is actually zero hosts in the hash */
    /* @todo: host_hash_for_each() */

    struct host_decl *host1 = 0, *host2 = 0, *host3 = 0;
    struct host_decl *check = 0;

    /* === step 1: allocate hosts === */
    ATF_CHECK_MSG(host_allocate(&host1, MDL) == ISC_R_SUCCESS,
                  "Failed to allocate host");
    ATF_CHECK_MSG(host_allocate(&host2, MDL) == ISC_R_SUCCESS,
                  "Failed to allocate host");
    ATF_CHECK_MSG(host_allocate(&host3, MDL) == ISC_R_SUCCESS,
                  "Failed to allocate host");

    ATF_CHECK_MSG(host_new_hash(&host_uid_hash, HOST_HASH_SIZE, MDL) != 0,
                  "Unable to create new hash");

    ATF_CHECK_MSG(buffer_allocate(&host1->client_identifier.buffer,
                                  clientid1_len, MDL) != 0,
                  "Can't allocate uid buffer for host1");
    ATF_CHECK_MSG(buffer_allocate(&host2->client_identifier.buffer,
                                  clientid2_len, MDL) != 0,
                  "Can't allocate uid buffer for host2");
    ATF_CHECK_MSG(buffer_allocate(&host3->client_identifier.buffer,
                                  clientid3_len, MDL) != 0,
                  "Can't allocate uid buffer for host3");

    /* verify that our hosts are not in the hash yet */
    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid1,
                                   clientid1_len, MDL) == 0,
                   "Host1 is not supposed to be in the uid_hash.");

    ATF_CHECK_MSG(!check, "Host1 is not supposed to be in the uid_hash.");

    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid2,
                                   clientid2_len, MDL) == 0,
                  "Host2 is not supposed to be in the uid_hash.");
    ATF_CHECK_MSG(!check, "Host2 is not supposed to be in the uid_hash.");

    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid3,
                                   clientid3_len, MDL) == 0,
                  "Host3 is not supposed to be in the uid_hash.");
    ATF_CHECK_MSG(!check, "Host3 is not supposed to be in the uid_hash.");

    /* === step 2: add hosts to the hash === */
    host_hash_add(host_uid_hash, clientid1, clientid1_len, host1, MDL);
    host_hash_add(host_uid_hash, clientid2, clientid2_len, host2, MDL);
    host_hash_add(host_uid_hash, clientid3, clientid3_len, host3, MDL);

    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid1,
                                   clientid1_len, MDL),
                  "Host1 was supposed to be in the uid_hash.");
    /* Hey! That's not the host we were looking for! */
    ATF_CHECK_MSG(check == host1, "Wrong host returned by host_hash_lookup");
    host_dereference(&check, MDL); /* we don't need it now */

    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid2,
                                   clientid2_len, MDL),
                  "Host2 was supposed to be in the uid_hash.");
    ATF_CHECK_MSG(check, "Host2 was supposed to be in the uid_hash.");
    /* Hey! That's not the host we were looking for! */
    ATF_CHECK_MSG(check == host2, "Wrong host returned by host_hash_lookup");
    host_dereference(&check, MDL); /* we don't need it now */

    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid3,
                                   clientid3_len, MDL),
                  "Host3 was supposed to be in the uid_hash.");
    ATF_CHECK_MSG(check, "Host3 was supposed to be in the uid_hash.");
    /* Hey! That's not the host we were looking for! */
    ATF_CHECK_MSG(check == host3, "Wrong host returned by host_hash_lookup");
    host_dereference(&check, MDL); /* we don't need it now */

    /* === step 4: remove first host from the hash === */

    /* delete host from hash */
    host_hash_delete(host_uid_hash, clientid1, clientid1_len, MDL);

    /* verify that host1 is no longer in the hash */
    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid1,
                                   clientid1_len, MDL) == 0,
                   "Host1 is not supposed to be in the uid_hash.");
    ATF_CHECK_MSG(!check, "Host1 is not supposed to be in the uid_hash.");

    /* host2 and host3 should be still there, though */
    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid2,
                                   clientid2_len, MDL),
                   "Host2 was supposed to still be in the uid_hash.");
    host_dereference(&check, MDL);
    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid3,
                                   clientid3_len, MDL),
                   "Host3 was supposed to still be in the uid_hash.");
    host_dereference(&check, MDL);

    /* === step 5: remove second host from the hash === */
    host_hash_delete(host_uid_hash, clientid2, clientid2_len, MDL);

    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid2,
                                   clientid2_len, MDL) == 0,
                   "Host2 was not supposed to be in the uid_hash anymore.");
    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid3,
                                   clientid3_len, MDL),
                   "Host3 was supposed to still be in the uid_hash.");
    host_dereference(&check, MDL);

    /* === step 6: remove the last (third) host from the hash === */
    host_hash_delete(host_uid_hash, clientid3, clientid3_len, MDL);

    ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid3,
                                   clientid3_len, MDL) == 0,
                   "Host3 was not supposed to be in the uid_hash anymore.");
    host_dereference(&check, MDL);


    host_dereference(&host1, MDL);
    host_dereference(&host2, MDL);
    host_dereference(&host3, MDL);

    /*
     * No easy way to check if the host object were actually released.
     * We could run it in valgrind and check for memory leaks.
     */

#if defined (DEBUG_MEMORY_LEAKAGE) && defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
    /* @todo: Should be called in cleanup */
    free_everything ();
#endif
}
Exemplo n.º 28
0
/* Determine what, if any, forward and reverse updates need to be
 * performed, and carry them through.
 */
int
ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
	     struct iasubopt *lease6, struct iasubopt *old6,
	     struct option_state *options)
{
	unsigned long ddns_ttl = DEFAULT_DDNS_TTL;
	struct data_string ddns_hostname;
	struct data_string ddns_domainname;
	struct data_string old_ddns_fwd_name;
	struct data_string ddns_fwd_name;
	struct data_string ddns_rev_name;
	struct data_string ddns_dhcid;
	struct binding_scope **scope;
	struct iaddr addr;
	struct data_string d1;
	struct option_cache *oc;
	int s1, s2;
	int result = 0;
	isc_result_t rcode1 = ISC_R_SUCCESS, rcode2 = ISC_R_SUCCESS;
	int server_updates_a = 1;
	int server_updates_ptr = 1;
	struct buffer *bp = (struct buffer *)0;
	int ignorep = 0, client_ignorep = 0;
	int rev_name_len;
	int i;

	if (ddns_update_style != 2)
		return 0;

	if (lease != NULL) {
		scope = &(lease->scope);
		addr = lease->ip_addr;
	} else if (lease6 != NULL) {
		scope = &(lease6->scope);
		memcpy(addr.iabuf, lease6->addr.s6_addr, 16);
		addr.len = 16;
	} else {
		log_fatal("Impossible condition at %s:%d.", MDL);
		/* Silence compiler warnings. */
		return 0;
	}

	memset(&d1, 0, sizeof(d1));
	memset (&ddns_hostname, 0, sizeof (ddns_hostname));
	memset (&ddns_domainname, 0, sizeof (ddns_domainname));
	memset (&old_ddns_fwd_name, 0, sizeof (ddns_fwd_name));
	memset (&ddns_fwd_name, 0, sizeof (ddns_fwd_name));
	memset (&ddns_rev_name, 0, sizeof (ddns_rev_name));
	memset (&ddns_dhcid, 0, sizeof (ddns_dhcid));

	/* If we are allowed to accept the client's update of its own A
	   record, see if the client wants to update its own A record. */
	if (!(oc = lookup_option(&server_universe, options,
				 SV_CLIENT_UPDATES)) ||
	    evaluate_boolean_option_cache(&client_ignorep, packet, lease, NULL,
					  packet->options, options, scope,
					  oc, MDL)) {
		/* If there's no fqdn.no-client-update or if it's
		   nonzero, don't try to use the client-supplied
		   XXX */
		if (!(oc = lookup_option (&fqdn_universe, packet -> options,
					  FQDN_SERVER_UPDATE)) ||
		    evaluate_boolean_option_cache(&ignorep, packet, lease,
						  NULL, packet->options,
						  options, scope, oc, MDL))
			goto noclient;
		/* Win98 and Win2k will happily claim to be willing to
		   update an unqualified domain name. */
		if (!(oc = lookup_option (&fqdn_universe, packet -> options,
					  FQDN_DOMAINNAME)))
			goto noclient;
		if (!(oc = lookup_option (&fqdn_universe, packet -> options,
					  FQDN_FQDN)) ||
		    !evaluate_option_cache(&ddns_fwd_name, packet, lease,
					   NULL, packet->options,
					   options, scope, oc, MDL))
			goto noclient;
		server_updates_a = 0;
		goto client_updates;
	}
      noclient:
	/* If do-forward-updates is disabled, this basically means don't
	   do an update unless the client is participating, so if we get
	   here and do-forward-updates is disabled, we can stop. */
	if ((oc = lookup_option (&server_universe, options,
				 SV_DO_FORWARD_UPDATES)) &&
	    !evaluate_boolean_option_cache(&ignorep, packet, lease,
					   NULL, packet->options,
					   options, scope, oc, MDL)) {
		return 0;
	}

	/* If it's a static lease, then don't do the DNS update unless we're
	   specifically configured to do so.   If the client asked to do its
	   own update and we allowed that, we don't do this test. */
	/* XXX: note that we cannot detect static DHCPv6 leases. */
	if ((lease != NULL) && (lease->flags & STATIC_LEASE)) {
		if (!(oc = lookup_option(&server_universe, options,
					 SV_UPDATE_STATIC_LEASES)) ||
		    !evaluate_boolean_option_cache(&ignorep, packet, lease,
						   NULL, packet->options,
						   options, scope, oc, MDL))
			return 0;
	}

	/*
	 * Compute the name for the A record.
	 */
	oc = lookup_option(&server_universe, options, SV_DDNS_HOST_NAME);
	if (oc)
		s1 = evaluate_option_cache(&ddns_hostname, packet, lease,
					   NULL, packet->options,
					   options, scope, oc, MDL);
	else
		s1 = 0;

	oc = lookup_option(&server_universe, options, SV_DDNS_DOMAIN_NAME);
	if (oc)
		s2 = evaluate_option_cache(&ddns_domainname, packet, lease,
					   NULL, packet->options,
					   options, scope, oc, MDL);
	else
		s2 = 0;

	if (s1 && s2) {
		if (ddns_hostname.len + ddns_domainname.len > 253) {
			log_error ("ddns_update: host.domain name too long");

			goto out;
		}

		buffer_allocate (&ddns_fwd_name.buffer,
				 ddns_hostname.len + ddns_domainname.len + 2,
				 MDL);
		if (ddns_fwd_name.buffer) {
			ddns_fwd_name.data = ddns_fwd_name.buffer -> data;
			data_string_append (&ddns_fwd_name, &ddns_hostname);
			ddns_fwd_name.buffer -> data [ddns_fwd_name.len] = '.';
			ddns_fwd_name.len++;
			data_string_append (&ddns_fwd_name, &ddns_domainname);
			ddns_fwd_name.buffer -> data [ddns_fwd_name.len] ='\0';
			ddns_fwd_name.terminated = 1;
		}
	}
      client_updates:

	/* See if there's a name already stored on the lease. */
	if (find_bound_string(&old_ddns_fwd_name, *scope, "ddns-fwd-name")) {
		/* If there is, see if it's different. */
		if (old_ddns_fwd_name.len != ddns_fwd_name.len ||
		    memcmp (old_ddns_fwd_name.data, ddns_fwd_name.data,
			    old_ddns_fwd_name.len)) {
			/* If the name is different, try to delete
			   the old A record. */
			if (!ddns_removals(lease, lease6))
				goto out;
			/* If the delete succeeded, go install the new
			   record. */
			goto in;
		}

		/* See if there's a DHCID on the lease, and if not
		 * then potentially look for 'on events' for ad-hoc ddns.
		 */
		if (!find_bound_string(&ddns_dhcid, *scope, "ddns-txt") &&
		    (old != NULL)) {
			/* If there's no DHCID, the update was probably
			   done with the old-style ad-hoc DDNS updates.
			   So if the expiry and release events look like
			   they're the same, run them.   This should delete
			   the old DDNS data. */
			if (old -> on_expiry == old -> on_release) {
				execute_statements(NULL, NULL, lease, NULL,
						   NULL, NULL, scope,
						   old->on_expiry);
				if (old -> on_expiry)
					executable_statement_dereference
						(&old -> on_expiry, MDL);
				if (old -> on_release)
					executable_statement_dereference
						(&old -> on_release, MDL);
				/* Now, install the DDNS data the new way. */
				goto in;
			}
		} else
			data_string_forget(&ddns_dhcid, MDL);

		/* See if the administrator wants to do updates even
		   in cases where the update already appears to have been
		   done. */
		if (!(oc = lookup_option(&server_universe, options,
					 SV_UPDATE_OPTIMIZATION)) ||
		    evaluate_boolean_option_cache(&ignorep, packet, lease,
						  NULL, packet->options,
						  options, scope, oc, MDL)) {
			result = 1;
			goto noerror;
		}
	/* If there's no "ddns-fwd-name" on the lease record, see if
	 * there's a ddns-client-fqdn indicating a previous client
	 * update (if it changes, we need to adjust the PTR).
	 */
	} else if (find_bound_string(&old_ddns_fwd_name, *scope,
				     "ddns-client-fqdn")) {
		/* If the name is not different, no need to update
		   the PTR record. */
		if (old_ddns_fwd_name.len == ddns_fwd_name.len &&
		    !memcmp (old_ddns_fwd_name.data, ddns_fwd_name.data,
			     old_ddns_fwd_name.len) &&
		    (!(oc = lookup_option(&server_universe, options,
					  SV_UPDATE_OPTIMIZATION)) ||
		     evaluate_boolean_option_cache(&ignorep, packet, lease,
						   NULL, packet->options,
						   options, scope, oc, MDL))) {
			goto noerror;
		}
	}
      in:
		
	/* If we don't have a name that the client has been assigned, we
	   can just skip all this. */
	if (!ddns_fwd_name.len)
		goto out;

	if (ddns_fwd_name.len > 255) {
		log_error ("client provided fqdn: too long");
		goto out;
	}

	/*
	 * Compute the RR TTL.
	 */
	ddns_ttl = DEFAULT_DDNS_TTL;
	if ((oc = lookup_option(&server_universe, options, SV_DDNS_TTL))) {
		if (evaluate_option_cache(&d1, packet, lease, NULL,
					  packet->options, options, scope,
					  oc, MDL)) {
			if (d1.len == sizeof (u_int32_t))
				ddns_ttl = getULong (d1.data);
			data_string_forget (&d1, MDL);
		}
	}

	/*
	 * Compute the reverse IP name, starting with the domain name.
	 */
	oc = lookup_option(&server_universe, options, SV_DDNS_REV_DOMAIN_NAME);
	if (oc)
		s1 = evaluate_option_cache(&d1, packet, lease, NULL,
					   packet->options, options,
					   scope, oc, MDL);
	else
		s1 = 0;

	/* 
	 * Figure out the length of the part of the name that depends 
	 * on the address.
	 */
	if (addr.len == 4) {
		char buf[17];
		/* XXX: WOW this is gross. */
		rev_name_len = snprintf(buf, sizeof(buf), "%u.%u.%u.%u.",
					addr.iabuf[3] & 0xff,
					addr.iabuf[2] & 0xff,
					addr.iabuf[1] & 0xff,
					addr.iabuf[0] & 0xff) + 1;

		if (s1) {
			rev_name_len += d1.len;

			if (rev_name_len > 255) {
				log_error("ddns_update: Calculated rev domain "
					  "name too long.");
				s1 = 0;
				data_string_forget(&d1, MDL);
			}
		}
	} else if (addr.len == 16) {
		/* 
		 * IPv6 reverse names are always the same length, with 
		 * 32 hex characters separated by dots.
		 */
		rev_name_len = sizeof("0.1.2.3.4.5.6.7."
				      "8.9.a.b.c.d.e.f."
				      "0.1.2.3.4.5.6.7."
				      "8.9.a.b.c.d.e.f."
				      "ip6.arpa.");

		/* Set s1 to make sure we gate into updates. */
		s1 = 1;
	} else {
		log_fatal("invalid address length %d", addr.len);
		/* Silence compiler warnings. */
		return 0;
	}

	/* See if we are configured NOT to do reverse ptr updates */
	if ((oc = lookup_option(&server_universe, options,
				SV_DO_REVERSE_UPDATES)) &&
	    !evaluate_boolean_option_cache(&ignorep, packet, lease, NULL,
					   packet->options, options,
					   scope, oc, MDL)) {
		server_updates_ptr = 0;
	}

	if (s1) {
		i=buffer_allocate(&ddns_rev_name.buffer, rev_name_len, MDL);
		if(!i){
			log_error("buffer_allocate failed!\n");
		}
		if (ddns_rev_name.buffer != NULL) {
			ddns_rev_name.data = ddns_rev_name.buffer->data;

			if (addr.len == 4) {
				ddns_rev_name.len =
				    sprintf((char *)ddns_rev_name.buffer->data,
					    "%u.%u.%u.%u.", 
					    addr.iabuf[3] & 0xff,
					    addr.iabuf[2] & 0xff,
					    addr.iabuf[1] & 0xff,
					    addr.iabuf[0] & 0xff);

				/*
				 * d1.data may be opaque, garbage bytes, from
				 * user (mis)configuration.
				 */
				data_string_append(&ddns_rev_name, &d1);
				ddns_rev_name.buffer->data[ddns_rev_name.len] =
					'\0';
			} else if (addr.len == 16) {
				char *p = (char *)&ddns_rev_name.buffer->data;
				unsigned char *a = addr.iabuf + 15;
				for (i=0; i<16; i++) {
					sprintf(p, "%x.%x.", 
						(*a & 0xF), ((*a >> 4) & 0xF));
					p += 4;
					a -= 1;
				}
				strcat(p, "ip6.arpa.");
				ddns_rev_name.len =
				    strlen((const char *)ddns_rev_name.data);
			}

			ddns_rev_name.terminated = 1;
		}
Exemplo n.º 29
0
int main (int argc, char **argv) {
  int i, j, iterations;
  pthread_t sensor_thread;
  // sample 3 times (0.3 sec)
  int sample_count = 1;

  // connect to sensor in new thread while we
  // initialize everything else
  sensor_thread = sensor_init_thread();

  scans = malloc(sample_count*sizeof(raw_sensor_scan));

  // allocate buffers
  for (i = 0; i < BUFFER_HISTORY; i++)
    map[i] = buffer_allocate();

  glutInit(&argc, argv);
  // pass size of buffer, then window size
  initGL(map[0], map[2], BUFFER_WIDTH, BUFFER_HEIGHT, ARENA_WIDTH/8, ARENA_HEIGHT/8);

  rand_normal_init();

  // wait for sensor
  assert(pthread_join(sensor_thread, NULL) == 0);

  // draw initial border
  for (i = 0; i < ARENA_WIDTH; i++)
    for (j = 0; j < 10*BUFFER_FACTOR; j += BUFFER_FACTOR) {
      record_map_position(1, i, j, 255);
      record_map_position(1, i, ARENA_HEIGHT - 1 - j, 255);
    }

  for (i = 0; i < ARENA_HEIGHT; i++)
    for (j = 0; j < 10*BUFFER_FACTOR; j+= BUFFER_FACTOR) {
      record_map_position(1, j, i, 255);
      record_map_position(1, ARENA_WIDTH - 1 - j, i, 255);
    }

  // start a scan
  sensor_thread = sensor_read_raw_n_thread(sample_count);

  iterations = 0;

  while(1) {
    swarm_init();

    // wait for sensor
    assert(pthread_join(sensor_thread, NULL) == 0);

    // get samples
    for (j = 0; j < sample_count; j++) {
      scans[j] = sensor_fetch_index(j);
    }

    // start a scan
    sensor_thread = sensor_read_raw_n_thread(sample_count);

    // give the swarm the new scans and the historical map
    swarm_filter(scans, map[1], sample_count);

    // update localization
    current_particle = swarm_get_best();

    // draw map from best particle
    for (i = 0; i < RAW_SENSOR_DISTANCES; i++)
      for (j = 0; j < sample_count; j++)
	record_distance(i, scans[j].distances[i]);

    // draw position
    double s, c, t;
    t = current_particle.theta*M_PI/180;
    s = sin(t);
    c = cos(t);
    for (i = -50; i < 51; i++)
      for (j = -50; j < 51; j++ ) {
	record_map_position(0, current_particle.x + i*c - j*s,
			    current_particle.y + i*s + j*c, 255);
	record_map_position(2, current_particle.x + i*c - j*s,
			    current_particle.y + i*s + j*c, 255);
      }

    // draw
    display();

    // clear position
    for (i = -50; i < 51; i++)
      for (j = -50; j < 51; j++ ) {
	record_map_position(0, current_particle.x + i*c - j*s,
			    current_particle.y + i*s + j*c, 0);
	if (!x_y_protected(current_particle.x + i*c - j*s, current_particle.y + i*s + j*c))
	  record_map_position(2, current_particle.x + i*c - j*s,
			      current_particle.y + i*s + j*c, 0);
      }

    // update historical map
    // and display map
    bzero(map[2], BUFFER_SIZE*sizeof(uint8_t));
    for (i = 0; i < BUFFER_SIZE; i++) {
      // j is our current value minus a threshold (200)
      j = map[0][i] - 200;
      // if the current buffer has a high value
      if (j > 0) {
	// add to historical buffer,
	// taking care not to wrap around
	if (map[1][i] + j <= 255)
	  map[1][i] += j;
	else
	  map[1][i] = 255;
      } else
	// if the current buffer does not have a high value,
	// the historical buffer is above zero,
	// the index is not protected, and the index is in the
	// scanner's visible arc, attenuate
	if (map[1][i] > 0 && !index_protected(i) && index_is_visible(i, current_particle, scans[0]))
	  map[1][i] *= 0.95;
      // only display a pixel if we are paying attention
      // to it in the particle filter (swarm.c:swarm_filter)
      if (map[1][i] > 200)
	map[2][i] = 255;
    }

    // attenuate current map
    buffer_attenuate(map[0], 0.75);

    glutMainLoopEvent();

    iterations++;
  }

  return 0;
}