Example #1
0
ni_buffer_t *
ni_file_read(FILE *fp)
{
	struct stat stb;
	unsigned int count, done, size;
	ni_buffer_t *result;

	if (fstat(fileno(fp), &stb) < 0)
		return NULL;

	if (S_ISREG(stb.st_mode)) {
		size = stb.st_size;

		result = ni_buffer_new_dynamic(size);
		if (result == NULL)
			return NULL;

		for (done = 0; done < size; done += count) {
			void *buffer = ni_buffer_tail(result);

			count = fread(buffer, 1, size - done, fp);
			if (count == 0)
				break;
			ni_buffer_push_tail(result, count);
		}
	} else {
		/* Could be a pipe or tty or socket */
		result = ni_buffer_new_dynamic(4096);
		if (result == NULL)
			return NULL;

		while (TRUE) {
			void *buffer;

			ni_buffer_ensure_tailroom(result, 4096);
			buffer = ni_buffer_tail(result);

			count = fread(buffer, 1, ni_buffer_tailroom(result), fp);
			if (count == 0)
				break;
			ni_buffer_push_tail(result, count);
		}
	}

	if (ferror(fp)) {
		ni_error("%s: read error on file", __func__);
		ni_buffer_free(result);
		return NULL;
	}

	return result;
}
Example #2
0
static ni_dhcp4_message_t *
__ni_dhcp4_build_msg_init_head(const ni_dhcp4_device_t *dev,
				unsigned int msg_code, ni_buffer_t *msgbuf)
{
	ni_dhcp4_message_t *message;

	/* Build the main message (header) */
	if (!(message = ni_buffer_push_tail(msgbuf, sizeof(*message)))) {
		ni_error("%s: buffer too short for dhcp4 message", dev->ifname);
		return NULL;
	}

	memset(message, 0, sizeof(*message));
	message->op = DHCP4_BOOTREQUEST;
	message->xid = dev->dhcp4.xid;
	message->secs = htons(ni_dhcp4_device_uptime(dev, 0xFFFF));
	message->cookie = htonl(MAGIC_COOKIE);
	message->hwtype = dev->system.hwaddr.type;

	ni_dhcp4_option_put8(msgbuf, DHCP4_MESSAGETYPE, msg_code);
	ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP,
			"%s: using message type: %s", dev->ifname,
			ni_dhcp4_message_name(msg_code));

	return message;
}
Example #3
0
/*
 * Filesystem.download(path, offset, count)
 *
 */
static dbus_bool_t
__ni_Testbus_Agent_Filesystem_download(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_dbus_variant_t res = NI_DBUS_VARIANT_INIT;
	const char *path;
	uint64_t offset;
	uint32_t count;
	dbus_bool_t rv;
	ni_buffer_t *bp = NULL;
	int fd = -1;

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

	if ((fd = open(path, O_RDONLY)) < 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;
	}

	bp = ni_buffer_new(count);
	while (count) {
		int n;

		n = read(fd, ni_buffer_tail(bp), ni_buffer_tailroom(bp));
		if (n < 0) {
			ni_dbus_set_error_from_errno(error, errno, "read failed");
			goto out_fail;
		}
		if (n == 0)
			break;
		ni_buffer_push_tail(bp, n);
	}

	ni_dbus_variant_init_dict(&res);
	ni_dbus_variant_set_byte_array(&res, ni_buffer_head(bp), ni_buffer_count(bp));

	rv = ni_dbus_message_serialize_variants(reply, 1, &res, error);

	ni_dbus_variant_destroy(&res);
	ni_buffer_free(bp);
	close(fd);
	return rv;

out_fail:
	if (fd >= 0)
		close(fd);
	return FALSE;
}
Example #4
0
File: arp.c Project: gsanso/wicked
int
ni_arp_send(ni_arp_socket_t *arph, const ni_arp_packet_t *packet)
{
	unsigned int hwlen, pktlen;
	struct arphdr *arp;
	ni_buffer_t buf;
	int rv;

	hwlen = ni_link_address_length(arph->dev_info.hwaddr.type);
	pktlen = sizeof(*arp) + 2 * hwlen + 2 * 4;

	arp = calloc(1, pktlen);
	ni_buffer_init(&buf, arp, pktlen);

	arp = ni_buffer_push_tail(&buf, sizeof(*arp));
	arp->ar_hrd = htons(arph->dev_info.hwaddr.type);
	arp->ar_pro = htons(ETHERTYPE_IP);
	arp->ar_hln = hwlen;
	arp->ar_pln = 4;
	arp->ar_op = htons(packet->op);

	if (packet->sha.len == hwlen) {
		ni_buffer_put(&buf, packet->sha.data, packet->sha.len);
	} else {
		ni_buffer_put(&buf, NULL, hwlen);
	}
	ni_buffer_put(&buf, &packet->sip, 4);
	if (packet->tha.len == hwlen) {
		ni_buffer_put(&buf, packet->tha.data, packet->tha.len);
	} else {
		ni_buffer_put(&buf, NULL, hwlen);
	}
	ni_buffer_put(&buf, &packet->tip, 4);

	rv = ni_capture_send(arph->capture, &buf, NULL);
	free(buf.base);
	return rv;
}
Example #5
0
ni_iaid_map_t *
ni_iaid_map_load(const char *filename)
{
	ni_iaid_map_t *map;
	const char *type;
	ni_buffer_t buff;
	struct stat stb;
	ssize_t len;

	if (!(map = ni_iaid_map_new())) {
		ni_error("unable to allocate memory for iaid map: %m");
		return NULL;
	}

	if (filename) {
		type = "given";
		if (!ni_string_dup(&map->file, filename)) {
			ni_error("unable to copy %s iaid map file name (%s): %m", type, filename);
			goto failure;
		}

		if (!ni_iaid_map_open(map)) {
			ni_error("unable to open %s iaid map file name (%s): %m", type, map->file);
			goto failure;
		}
	} else {
		type = "default";
		if (!ni_iaid_map_set_default_file(&map->file)) {
			ni_error("unable to construct %s iaid map file name: %m", type);
			goto failure;
		}

		if (!ni_iaid_map_open(map)) {
			ni_debug_readwrite("unable to open %s iaid map file name (%s): %m", type, map->file);

			type = "fallback";
			if (!ni_iaid_map_set_fallback_file(&map->file)) {
				ni_error("unable to construct %s iaid map file name: %m", type);
				goto failure;
			}
			
			if (!ni_iaid_map_open(map)) {
				ni_error("unable to open iaid map file name (%s): %m", map->file);
				goto failure;
			}
		}
	}

	if (!ni_iaid_map_lock(map)) {
		ni_error("unable to lock %s iaid map file name (%s): %m", type, map->file);
		goto failure;
	}

	if (fstat(map->fd, &stb) < 0)
		stb.st_size = BUFSIZ;

	ni_buffer_init_dynamic(&buff, stb.st_size + 1);
	do {
		if (!ni_buffer_tailroom(&buff))
			ni_buffer_ensure_tailroom(&buff, BUFSIZ);

		do {
			 len = read(map->fd, ni_buffer_tail(&buff), ni_buffer_tailroom(&buff));
			 if (len > 0)
				 ni_buffer_push_tail(&buff, len);
		} while (len < 0 && errno == EINTR);
	} while (len > 0);

	if (len < 0) {
		ni_error("unable to read %s iaid map file name (%s): %m", type, map->file);
	} else {
		map->doc = xml_document_from_buffer(&buff, map->file);
		ni_buffer_destroy(&buff);
		if (!map->doc) {
			map->doc = xml_document_new();
			ni_warn("unable to parse %s iaid map file name (%s): %m", type, map->file);
		}
		return map;
	}

failure:
	ni_iaid_map_free(map);
	return NULL;
}
Example #6
0
int
ni_dhcp_build_message(const ni_dhcp_device_t *dev,
			unsigned int msg_code,
			const ni_addrconf_lease_t *lease,
			ni_buffer_t *msgbuf)
{
	const ni_dhcp_config_t *options = dev->config;
	struct in_addr src_addr, dst_addr;
	ni_dhcp_message_t *message = NULL;

	if (!options || !lease)
		return -1;

	if (IN_LINKLOCAL(ntohl(lease->dhcp.address.s_addr))) {
		ni_error("cannot request a link local address");
		goto failed;
	}

	src_addr.s_addr = dst_addr.s_addr = 0;
	switch (msg_code) {
	case DHCP_DISCOVER:
		if (lease->dhcp.serveraddress.s_addr != 0)
			return -1;
		break;

	case DHCP_REQUEST:
	case DHCP_RELEASE:
	case DHCP_INFORM:
		if (lease->dhcp.address.s_addr == 0 || lease->dhcp.serveraddress.s_addr == 0)
			return -1;
		src_addr = lease->dhcp.address;
		dst_addr = lease->dhcp.serveraddress;
		break;
	}

	/* Reserve some room for the IP and UDP header */
	ni_buffer_reserve_head(msgbuf, sizeof(struct ip) + sizeof(struct udphdr));

	/* Build the message */
	message = ni_buffer_push_tail(msgbuf, sizeof(*message));

	message->op = DHCP_BOOTREQUEST;
	message->hwtype = dev->system.arp_type;
	message->xid = dev->dhcp.xid;
	message->cookie = htonl(MAGIC_COOKIE);
	message->secs = htons(ni_dhcp_device_uptime(dev, 0xFFFF));

	if (dev->fsm.state == NI_DHCP_STATE_BOUND
	 || dev->fsm.state == NI_DHCP_STATE_RENEWING
	 || dev->fsm.state == NI_DHCP_STATE_REBINDING)
		message->ciaddr = lease->dhcp.address.s_addr;

	switch (dev->system.arp_type) {
	case ARPHRD_ETHER:
	case ARPHRD_IEEE802:
		if (dev->system.hwaddr.len > sizeof(message->chaddr)) {
			ni_error("dhcp cannot handle hwaddress length %u",
					dev->system.hwaddr.len);
			goto failed;
		}
		message->hwlen = dev->system.hwaddr.len;
		memcpy(&message->chaddr, dev->system.hwaddr.data, dev->system.hwaddr.len);
		break;

	case ARPHRD_IEEE1394:
	case ARPHRD_INFINIBAND:
		message->hwlen = 0;
		if (message->ciaddr == 0)
			message->flags = htons(BROADCAST_FLAG);
		break;

	default:
		ni_error("dhcp: unknown hardware type %d", dev->system.arp_type);
	}

	ni_dhcp_option_put8(msgbuf, DHCP_MESSAGETYPE, msg_code);

	if (msg_code == DHCP_REQUEST)
		ni_dhcp_option_put16(msgbuf, DHCP_MAXMESSAGESIZE, dev->system.mtu);

	ni_dhcp_option_put(msgbuf, DHCP_CLIENTID,
			options->raw_client_id.data,
			options->raw_client_id.len);

	if (msg_code != DHCP_DECLINE && msg_code != DHCP_RELEASE) {
		if (options->userclass.len > 0)
			ni_dhcp_option_put(msgbuf, DHCP_USERCLASS,
					options->userclass.data,
					options->userclass.len);

		if (options->classid && options->classid[0])
			ni_dhcp_option_puts(msgbuf, DHCP_CLASSID, options->classid);
	}

	if (msg_code == DHCP_DISCOVER || msg_code == DHCP_REQUEST) {
		if (lease->dhcp.address.s_addr)
			ni_dhcp_option_put_ipv4(msgbuf, DHCP_ADDRESS, lease->dhcp.address);
		if (lease->dhcp.lease_time != 0)
			ni_dhcp_option_put32(msgbuf, DHCP_LEASETIME, lease->dhcp.lease_time);
	}

	if (msg_code == DHCP_REQUEST) {
		if (lease->dhcp.serveraddress.s_addr)
			ni_dhcp_option_put_ipv4(msgbuf, DHCP_SERVERIDENTIFIER, lease->dhcp.serveraddress);
	}

	if (msg_code == DHCP_DISCOVER || msg_code == DHCP_INFORM || msg_code == DHCP_REQUEST) {
		unsigned int params_begin;

		if (options->hostname && options->hostname[0]) {
			if (options->fqdn == FQDN_DISABLE) {
				ni_dhcp_option_puts(msgbuf, DHCP_HOSTNAME, options->hostname);
			} else {
				/* IETF DHC-FQDN option(81)
				 * http://tools.ietf.org/html/rfc4702#section-2.1
				 *
				 * Flags: 0000NEOS
				 * S: 1 => Client requests Server to update
				 *         a RR in DNS as well as PTR
				 * O: 1 => Server indicates to client that
				 *         DNS has been updated
				 * E: 1 => Name data is DNS format
				 * N: 1 => Client requests Server to not
				 *         update DNS
				 */
				ni_buffer_putc(msgbuf, DHCP_FQDN);
				ni_buffer_putc(msgbuf, strlen(options->hostname) + 3);
				ni_buffer_putc(msgbuf, options->fqdn & 0x9);
				ni_buffer_putc(msgbuf, 0);	/* from server for PTR RR */
				ni_buffer_putc(msgbuf, 0);	/* from server for A RR if S=1 */
				ni_buffer_put(msgbuf, options->hostname, strlen(options->hostname));
			}
		}

		params_begin = ni_dhcp_option_begin(msgbuf, DHCP_PARAMETERREQUESTLIST);

		if (msg_code == DHCP_DISCOVER) {
			/* dhcpcd says we should include just a single option
			 * in discovery packets.
			 * I'm not convinced this is right, but let's do it
			 * this way.
			 */
			ni_buffer_putc(msgbuf, DHCP_DNSSERVER);
		} else {
			if (msg_code != DHCP_INFORM) {
				ni_buffer_putc(msgbuf, DHCP_RENEWALTIME);
				ni_buffer_putc(msgbuf, DHCP_REBINDTIME);
			}
			ni_buffer_putc(msgbuf, DHCP_NETMASK);
			ni_buffer_putc(msgbuf, DHCP_BROADCAST);

			if (options->flags & DHCP_DO_CSR)
				ni_buffer_putc(msgbuf, DHCP_CSR);
			if (options->flags & DHCP_DO_MSCSR)
				ni_buffer_putc(msgbuf, DHCP_MSCSR);

			/* RFC 3442 states classless static routes should be
			 * before routers and static routes as classless static
			 * routes override them both */
			ni_buffer_putc(msgbuf, DHCP_STATICROUTE);
			ni_buffer_putc(msgbuf, DHCP_ROUTERS);
			ni_buffer_putc(msgbuf, DHCP_HOSTNAME);
			ni_buffer_putc(msgbuf, DHCP_DNSSEARCH);
			ni_buffer_putc(msgbuf, DHCP_DNSDOMAIN);
			ni_buffer_putc(msgbuf, DHCP_DNSSERVER);

			if (options->flags & DHCP_DO_NIS) {
				ni_buffer_putc(msgbuf, DHCP_NISDOMAIN);
				ni_buffer_putc(msgbuf, DHCP_NISSERVER);
			}
			if (options->flags & DHCP_DO_NTP)
				ni_buffer_putc(msgbuf, DHCP_NTPSERVER);
			ni_buffer_putc(msgbuf, DHCP_MTU);
			ni_buffer_putc(msgbuf, DHCP_ROOTPATH);
			ni_buffer_putc(msgbuf, DHCP_SIPSERVER);
			ni_buffer_putc(msgbuf, DHCP_LPRSERVER);
			ni_buffer_putc(msgbuf, DHCP_LOGSERVER);
			ni_buffer_putc(msgbuf, DHCP_NETBIOSNAMESERVER);
			ni_buffer_putc(msgbuf, DHCP_NETBIOSDDSERVER);
			ni_buffer_putc(msgbuf, DHCP_NETBIOSNODETYPE);
			ni_buffer_putc(msgbuf, DHCP_NETBIOSSCOPE);
		}

		ni_dhcp_option_end(msgbuf, params_begin);
	}
	ni_buffer_putc(msgbuf, DHCP_END);

#ifdef BOOTP_MESSAGE_LENGTH_MIN
	ni_buffer_pad(msgbuf, BOOTP_MESSAGE_LENGTH_MIN, DHCP_PAD);
#endif

	if (ni_capture_build_udp_header(msgbuf, src_addr, DHCP_CLIENT_PORT, dst_addr, DHCP_SERVER_PORT) < 0) {
		ni_error("unable to build packet header");
		goto failed;
	}

	return 0;

failed:
	return -1;
}