Exemple #1
0
/*
 * Open ARP socket
 */
ni_arp_socket_t *
ni_arp_socket_open(const ni_capture_devinfo_t *dev_info, ni_arp_callback_t *callback, void *calldata)
{
	ni_capture_protinfo_t prot_info;
	ni_arp_socket_t *arph;

	arph = calloc(1, sizeof(*arph));
	arph->dev_info = *dev_info;
	arph->callback = callback;
	arph->user_data = calldata;

	memset(&prot_info, 0, sizeof(prot_info));
	prot_info.eth_protocol = ETHERTYPE_ARP;

	arph->capture = ni_capture_open(dev_info, &prot_info, ni_arp_socket_recv);
	if (!arph->capture) {
		ni_arp_socket_close(arph);
		return NULL;
	}

	ni_capture_set_user_data(arph->capture, arph);
	return arph;
}
Exemple #2
0
/*
 * Open a DHCP socket for send and receive
 */
int
ni_dhcp_socket_open(ni_dhcp_device_t *dev)
{
	ni_capture_protinfo_t prot_info;
	ni_capture_t *capture;

	/* We need to bind to a port, otherwise Linux will generate
	 * ICMP_UNREACHABLE messages telling the server that there's
	 * no DHCP client listening at all.
	 *
	 * We don't actually use this fd at all, instead using our packet
	 * filter socket.
	 *
	 * (It would be nice if we did, at least in BOUND/RENEWING state
	 * where good manners would dictate unicast requests anyway).
	 */
	if (dev->listen_fd == -1) {
		struct sockaddr_in sin;
		struct ifreq ifr;
		int on = 1;
		int fd;

		if ((fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
			ni_error("socket: %m");
			return -1;
		}

		if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
			ni_error("SO_REUSEADDR: %m");
		if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &on, sizeof(on)) == -1)
			ni_error("SO_RCVBUF: %m");

		memset(&ifr, 0, sizeof(ifr));
		strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
		if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1)
			ni_error("SO_SOBINDTODEVICE: %m");

		memset(&sin, 0, sizeof(sin));
		sin.sin_family = AF_INET;
		sin.sin_port = htons(DHCP_CLIENT_PORT);
		if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1) {
			ni_error("bind: %m");
			close(fd);
		} else {
			dev->listen_fd = fd;
			fcntl(fd, F_SETFD, FD_CLOEXEC);
		}
	}

	memset(&prot_info, 0, sizeof(prot_info));
	prot_info.eth_protocol = ETHERTYPE_IP;
	prot_info.ip_protocol = IPPROTO_UDP;
	prot_info.ip_port = DHCP_CLIENT_PORT;

	if ((capture = dev->capture) != NULL) {
		if (ni_capture_is_valid(capture, ETHERTYPE_IP))
			return 0;

		ni_capture_free(dev->capture);
		dev->capture = NULL;
	}

	dev->capture = ni_capture_open(&dev->system, &prot_info, ni_dhcp_socket_recv);
	if (!dev->capture)
		return -1;

	ni_capture_set_user_data(dev->capture, dev);
	return 0;
}