Exemple #1
0
//We need this function in addition to netpoll_wrapper_rx_handler() because pre-3.15 kernel versions 
//will not call the rx handler for the packets matching the IP/port of our netpoll objects (expecting them
//to be handled in rx_hook that we don't use because it provides no way of reading the MAC address).
static void hook_receive_skb(void *pContext, struct sk_buff *skb)
{
	int ulen;
	struct iphdr *iph;
	struct udphdr *uh;

	struct netpoll_wrapper *pWrapper = (struct netpoll_wrapper *)pContext;
	BUG_ON(!pWrapper);
	if (skb->dev != pWrapper->pDeviceWithHandler)
		return;

	if (pWrapper->handle_arp && skb->protocol == htons(ETH_P_ARP))
	{
		netpoll_wrapper_handle_arp(pWrapper, skb);
		return;
	}

	if (!parse_udp_packet(skb, &iph, &uh, &ulen))
		return;

	if (pWrapper->netpoll_obj.local_port && pWrapper->netpoll_obj.local_port == ntohs(uh->dest))
	{
		if ((ip_addr_as_int(pWrapper->netpoll_obj.local_ip) && ip_addr_as_int(pWrapper->netpoll_obj.local_ip) == iph->daddr) ||
			(support_broadcast_packets && iph->daddr == 0xffffffff))
		{
			pWrapper->netpoll_obj.remote_port = ntohs(uh->source);
			ip_addr_as_int(pWrapper->netpoll_obj.remote_ip) = iph->saddr;
			memcpy(pWrapper->netpoll_obj.remote_mac, eth_hdr(skb)->h_source, sizeof(pWrapper->netpoll_obj.remote_mac));

			if (pWrapper->pReceiveHandler)
				pWrapper->pReceiveHandler(pWrapper, ntohs(uh->source), (char *)(uh + 1), ulen - sizeof(struct udphdr));
		}
	}
}
Exemple #2
0
static void netpoll_wrapper_handle_arp(struct netpoll_wrapper *pWrapper, struct sk_buff *skb)
{
	struct arphdr *arp;
	unsigned char *arp_ptr;
	unsigned char *sha;
	__be32 sip, tip;

	if (!pskb_may_pull(skb, arp_hdr_len(skb->dev)))
		return;

	skb_reset_network_header(skb);
	skb_reset_transport_header(skb);
	arp = arp_hdr(skb);

	if ((arp->ar_hrd != htons(ARPHRD_ETHER) &&
		arp->ar_hrd != htons(ARPHRD_IEEE802)) ||
		arp->ar_pro != htons(ETH_P_IP) ||
		arp->ar_op != htons(ARPOP_REQUEST))
		return;

	arp_ptr = (unsigned char *)(arp + 1);
	/* save the location of the src hw addr */
	sha = arp_ptr;
	arp_ptr += skb->dev->addr_len;
	memcpy(&sip, arp_ptr, 4);
	arp_ptr += 4;
	/* If we actually cared about dst hw addr,
	it would get copied here */
	arp_ptr += skb->dev->addr_len;
	memcpy(&tip, arp_ptr, 4);

	/* Should we ignore arp? */
	if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip))
		return;

	if (tip != ip_addr_as_int(pWrapper->netpoll_obj.local_ip))
		return;	//This ARP request is not for our IP address

	for (int i = 0; i < ARRAY_SIZE(pWrapper->pending_arp_replies); i++)
	{
		if (!pWrapper->pending_arp_replies[i].valid)
		{
			pWrapper->pending_arp_replies[i].local_ip = tip;
			pWrapper->pending_arp_replies[i].remote_ip = sip;
			memcpy(pWrapper->pending_arp_replies[i].remote_mac, sha, sizeof(pWrapper->pending_arp_replies[i].remote_mac));
			pWrapper->pending_arp_replies[i].valid = true;
			break;
		}
	}
}
Exemple #3
0
int kgdboe_io_init(const char *device_name, int port, const char *local_ip,
		   bool force_single_core)
{
	int err;
	u8 ipaddr[4];

	spin_lock_init(&exception_lock);

	s_pKgdboeNetpoll = netpoll_wrapper_create(device_name, port, local_ip);
	if (!s_pKgdboeNetpoll)
		return -EINVAL;

	if (force_single_core) {
		force_single_cpu_mode();
	} else if (!nethook_initialize(s_pKgdboeNetpoll->pDeviceWithHandler)) {
		printk(KERN_ERR "kgdboe: failed to guarantee cross-CPU network "
				"API synchronization. Aborting. Try enabling "
				"single-CPU mode.\n");
		return -EINVAL;
	}

	err = kgdb_register_io_module(&kgdboe_io_ops);
	if (err != 0) {
		netpoll_wrapper_free(s_pKgdboeNetpoll);
		s_pKgdboeNetpoll = NULL;
		return err;
	}

	netpoll_wrapper_set_callback(s_pKgdboeNetpoll, kgdboe_rx_handler, NULL);

	memcpy(ipaddr, &ip_addr_as_int(s_pKgdboeNetpoll->netpoll_obj.local_ip),
	       4);
	printk(KERN_INFO "kgdboe: Successfully initialized. Use the following "
			 "gdb command to attach:\n");
	printk(KERN_INFO "\ttarget remote udp:%d.%d.%d.%d:%d\n", ipaddr[0],
	       ipaddr[1], ipaddr[2], ipaddr[3],
	       s_pKgdboeNetpoll->netpoll_obj.local_port);

	return 0;
}
Exemple #4
0
//We need this in addition to hook_receive_skb() because not dropping a packet
//while stopped in gdb may invoke some processing functions from the network stack that
//would like to take resources owned by other cores (that are now stopped).
//We don't want to guess and pre-acquire those resources, so we just drop all packets while stopped in kgdb.
static rx_handler_result_t netpoll_wrapper_rx_handler(struct sk_buff **pskb)
{
	struct netpoll_wrapper *pWrapper = (struct netpoll_wrapper *)(*pskb)->dev->rx_handler_data;
	bool drop = false;
	BUG_ON(!pWrapper);

	if (pWrapper->drop_other_packets)
		drop = true;
	else
	{
		int ulen;
		struct iphdr *iph;
		struct udphdr *uh;

		if (parse_udp_packet(*pskb, &iph, &uh, &ulen))
		{
			if (pWrapper->netpoll_obj.local_port && pWrapper->netpoll_obj.local_port == ntohs(uh->dest) && (ip_addr_as_int(pWrapper->netpoll_obj.local_ip) && ip_addr_as_int(pWrapper->netpoll_obj.local_ip) == iph->daddr))
			{
				//Otherwise Linux itself may handle it, reply with ICMP 'port not available' and force GDB to disconnect.
				drop = true;
			}
		}
	}

	if (drop)
	{
		kfree_skb(*pskb);
		return RX_HANDLER_CONSUMED;
	}
	else
		return RX_HANDLER_PASS;
}