Exemplo n.º 1
0
/*
 * Tmpfile.upload(path, offset, data)
 */
static dbus_bool_t
__ni_Testbus_Agent_Filesystem_upload(ni_dbus_object_t *object, const ni_dbus_method_t *method,
		unsigned int argc, const ni_dbus_variant_t *argv,
		ni_dbus_message_t *reply, DBusError *error)
{
	ni_buffer_t wbuf;
	const char *path;
	uint64_t offset;
	unsigned int written = 0;
	int fd;

	if (argc != 3
	 || !ni_dbus_variant_get_string(&argv[0], &path) || path[0] != '/'
	 || !ni_dbus_variant_get_uint64(&argv[1], &offset)
	 || !ni_dbus_variant_is_byte_array(&argv[2]))
		return ni_dbus_error_invalid_args(error, object->path, method->name);

	if (offset == 0)
		fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, 0644);
	else
		fd = open(path, O_WRONLY);
	if (fd < 0) {
		ni_dbus_set_error_from_errno(error, errno, "unable to open file \"%s\"", path);
		return FALSE;
	}
	if (lseek(fd, offset, SEEK_SET) < 0) {
		ni_dbus_set_error_from_errno(error, errno, "seek faile");
		goto out_fail;
	}

	ni_buffer_init_reader(&wbuf, argv[2].byte_array_value, argv[2].array.len);
	while (ni_buffer_count(&wbuf)) {
		int n;

		n = write(fd, ni_buffer_head(&wbuf), ni_buffer_count(&wbuf));
		if (n < 0) {
			ni_dbus_set_error_from_errno(error, errno,
						"error writing to \"%s\" at offset %Lu",
						path, (unsigned long long) offset + written);
			goto out_fail;
		}

		ni_buffer_pull_head(&wbuf, n);
		written += n;
	}

	close(fd);

	ni_debug_testbus("%s: wrote %u bytes at offset %Lu",
			path, written, (unsigned long long) offset);
	return TRUE;

out_fail:
	if (fd >= 0)
		close(fd);
	return FALSE;
}
Exemplo n.º 2
0
Arquivo: arp.c Projeto: gsanso/wicked
int
ni_arp_parse(ni_arp_socket_t *arph, ni_buffer_t *bp, ni_arp_packet_t *p)
{
	struct arphdr *arp;

	if (!(arp = ni_buffer_pull_head(bp, sizeof(*arp))))
		return -1;

	if (arp->ar_pro != htons(ETHERTYPE_IP)
	 || arp->ar_pln != 4)
		return -1;

	p->op = ntohs(arp->ar_op);
	p->sha.type = arph->dev_info.hwaddr.type;
	p->sha.len = ni_link_address_length(arph->dev_info.hwaddr.type);
	p->tha = p->sha;

	if (ni_buffer_get(bp, p->sha.data, p->sha.len) < 0 || ni_buffer_get(bp, &p->sip, 4) < 0
	 || ni_buffer_get(bp, p->tha.data, p->tha.len) < 0 || ni_buffer_get(bp, &p->tip, 4) < 0)
		return -1;

	return 0;
}
Exemplo n.º 3
0
int
ni_dhcp4_fsm_process_dhcp4_packet(ni_dhcp4_device_t *dev, ni_buffer_t *msgbuf)
{
	ni_dhcp4_message_t *message;
	ni_addrconf_lease_t *lease = NULL;
	int msg_code;

	if (dev->fsm.state == NI_DHCP4_STATE_VALIDATING) {
		/* We arrive here, when some dhcp4 packet arrives after
		 * we've got and processed an ACK already. Just ignore.
		 */
		ni_debug_dhcp("%s: ignoring dhcp4 packet arrived in state VALIDATING",
				dev->ifname);
		return -1;
	}

	if (!(message = ni_buffer_pull_head(msgbuf, sizeof(*message)))) {
		ni_debug_dhcp("short DHCP4 packet (%u bytes)", ni_buffer_count(msgbuf));
		return -1;
	}
	if (dev->dhcp4.xid == 0) {
		ni_debug_dhcp("unexpected packet on %s", dev->ifname);
		return -1;
	}
	if (dev->dhcp4.xid != message->xid) {
		ni_debug_dhcp("ignoring packet with wrong xid 0x%x (expected 0x%x)",
				message->xid, dev->dhcp4.xid);
		return -1;
	}

	msg_code = ni_dhcp4_parse_response(message, msgbuf, &lease);
	if (msg_code < 0) {
		/* Ignore this message, time out later */
		ni_error("unable to parse DHCP4 response");
		return -1;
	}

	/* set reqest client-id in the response early to have it in test mode */
	ni_opaque_set(&lease->dhcp4.client_id,	dev->config->client_id.data,
						dev->config->client_id.len);

	ni_debug_dhcp("%s: received %s message in state %s",
			dev->ifname, ni_dhcp4_message_name(msg_code),
			ni_dhcp4_fsm_state_name(dev->fsm.state));

	/* When receiving a DHCP4 OFFER, verify sender address against list of
	 * servers to ignore, and preferred servers. */
	if (msg_code == DHCP4_OFFER && dev->fsm.state == NI_DHCP4_STATE_SELECTING) {
		struct in_addr srv_addr = lease->dhcp4.server_id;
		int weight = 0;

		if (ni_dhcp4_config_ignore_server(srv_addr)) {
			ni_debug_dhcp("%s: ignoring DHCP4 offer from %s",
					dev->ifname, inet_ntoa(srv_addr));
			goto out;
		}

		/* If we're scanning all offers, we need to decide whether
		 * this offer is accepted, or whether we want to wait for
		 * more.
		 */
		if (!dev->dhcp4.accept_any_offer) {

			/* Check if we have any preferred servers. */
			weight = ni_dhcp4_config_server_preference(srv_addr);

			/* If we're refreshing an existing lease (eg after link disconnect
			 * and reconnect), we accept the offer if it comes from the same
			 * server as the original one.
			 */
			if (dev->lease
			 && dev->lease->dhcp4.server_id.s_addr == srv_addr.s_addr)
				weight = 100;

			ni_debug_dhcp("received lease offer from %s; server weight=%d (best offer=%d)",
					inet_ntoa(lease->dhcp4.server_id), weight,
					dev->best_offer.weight);

			/* negative weight means never. */
			if (weight < 0)
				goto out;

			/* weight between 0 and 100 means maybe. */
			if (weight < 100) {
				if (dev->best_offer.weight < weight) {
					ni_dhcp4_device_set_best_offer(dev, lease, weight);
					return 0;
				}
				goto out;
			}
			/* If the weight has maximum value, just accept this offer. */
		}
		ni_dhcp4_device_set_best_offer(dev, lease, weight);
		lease = NULL;
	}

	/* We've received a valid response; if something goes wrong now
	 * it's nothing that could be fixed by retransmitting the message.
	 *
	 * The only exception would be if we ever do some filtering or
	 * matching of OFFERs - then we would certainly want to keep
	 * waiting for additional packets.
	 */
	ni_dhcp4_device_disarm_retransmit(dev);
	dev->dhcp4.xid = 0;

	/* move to next stage of protocol */
	switch (msg_code) {
	case DHCP4_OFFER:
		if (dev->fsm.state != NI_DHCP4_STATE_SELECTING)
			goto ignore;

		/* process best offer set above */
		ni_dhcp4_process_offer(dev, dev->best_offer.lease);
		break;

	case DHCP4_ACK:
		if (dev->fsm.state == NI_DHCP4_STATE_INIT) {
			/*
			 * Received a decline ACK -- wait until
			 * timeout before we restart from begin
			 */
			ni_dhcp4_device_drop_lease(dev);
			break;
		}

		if (dev->fsm.state != NI_DHCP4_STATE_REQUESTING
		 && dev->fsm.state != NI_DHCP4_STATE_RENEWING
		 && dev->fsm.state != NI_DHCP4_STATE_REBOOT
		 && dev->fsm.state != NI_DHCP4_STATE_REBINDING)
			goto ignore;

		ni_dhcp4_process_ack(dev, lease);
		lease = NULL;
		break;

	case DHCP4_NAK:
		/* The RFC 2131 state diagram says, ignore NAKs in state BOUND.
		 * I guess we also have no use for NAK replies to a DHCP4_DISCOVER
		 */
		if (dev->fsm.state == NI_DHCP4_STATE_SELECTING
		 || dev->fsm.state == NI_DHCP4_STATE_BOUND)
			goto ignore;

		ni_dhcp4_process_nak(dev);
		break;

	default:
	ignore:
		ni_debug_dhcp("ignoring %s in state %s",
				ni_dhcp4_message_name(msg_code),
				ni_dhcp4_fsm_state_name(dev->fsm.state));
		break;
	}

out:
	if (lease && dev->lease != lease)
		ni_addrconf_lease_free(lease);

	/* If we received a message other than NAK, reset the NAK
	 * backoff timer. */
	if (msg_code != DHCP4_NAK)
		dev->dhcp4.nak_backoff = 1;

	return 0;
}