//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; }
static int pares_ipv4_packet(struct sk_buff *skb, struct iphdr *iphdr, dba_result_t *res) { int ret = 0; if (unlikely(!iphdr)) { return -1; } switch (iphdr->protocol) { case IPPROTO_ICMP: ret = parse_icmp_packet(skb, (struct icmphdr *)(IPv4_NXT_HDR(iphdr)), res); break; case IPPROTO_IGMP: ret = parse_igmp_packet(skb, (struct igmphdr *)(IPv4_NXT_HDR(iphdr)), res); break; case IPPROTO_TCP: ret = parse_tcp_packet(skb, (struct tcphdr *)(IPv4_NXT_HDR(iphdr)), res); break; case IPPROTO_UDP: ret = parse_udp_packet(skb, (struct udphdr *)(IPv4_NXT_HDR(iphdr)), res); break; case IPPROTO_IPV6: break; default: break; } return ret; }
//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)); } } }
bool CTDMHttpRequest::decode( CUdpCommonBufMsgBody* msgBody ) { int len = msgBody->Size(); if ( len <= 0 ) return false; int ret = parse_udp_packet( msgBody->GetBuf(), len ); if ( ret == -1 ) { WriteRunInfo::WriteLog( "parse http request packet error" ); return false; } return true; }
boolean parse_packet(struct sk_buff *skb, struct sniffed_packet_descr_t *descr) { struct iphdr *ip_header; /* we only handle packets, which are big enough * to contain an IP-header. */ if(skb->len < sizeof(struct iphdr) ) return FALSE; ip_header = (struct iphdr *) skb->data; /* check range of IHL-field */ if(ip_header->ihl < 5 || ip_header->ihl > 15) return FALSE; /* check ihl against skb-len */ if(skb->len < ip_header->ihl * 4) return FALSE; /* It has been verified that skb->data[0] to skb->data[ihl*4-1] * is readable. Extract information from ip-header */ descr->subject = descr->src = ip_header->saddr; if(ip_header->protocol == IPPROTO_TCP) return parse_tcp_packet(skb, descr); else if(ip_header->protocol == IPPROTO_ICMP) return parse_icmp_packet(skb, descr); else if(ip_header->protocol == IPPROTO_UDP) return parse_udp_packet(skb, descr); return FALSE; }