/** * nfq_ip_mangle - mangle IPv4 packet buffer * \param pktb: pointer to network packet buffer * \param dataoff: offset to layer 4 header * \param match_offset: offset to content that you want to mangle * \param match_len: length of the existing content you want to mangle * \param rep_buffer: pointer to data you want to use to replace current content * \param rep_len: length of data you want to use to replace current content * * \note This function recalculates the IPv4 checksum (if needed). */ int nfq_ip_mangle(struct pkt_buff *pkt, unsigned int dataoff, unsigned int match_offset, unsigned int match_len, const char *rep_buffer, unsigned int rep_len) { struct iphdr *iph = (struct iphdr *) pkt->network_header; if (!pktb_mangle(pkt, dataoff, match_offset, match_len, rep_buffer, rep_len)) return 0; /* fix IP hdr checksum information */ iph->tot_len = htons(pkt->len); nfq_ip_set_checksum(iph); return 1; }
static int cb( struct nfq_q_handle *q, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *arg ) { int id = 0; struct nfqnl_msg_packet_hdr *ph; size_t packet_length; unsigned char *packet_data; struct pkt_buff *packet; struct iphdr *ip_header; struct tcphdr *tcp_header; ph = nfq_get_msg_packet_hdr(nfa); if (ph) { id = ntohl(ph->packet_id); } packet_length = nfq_get_payload(nfa, &packet_data); packet = pktb_alloc(AF_INET, packet_data, packet_length, 4096); ip_header = nfq_ip_get_hdr(packet); nfq_ip_set_transport_header(packet, ip_header); tcp_header = nfq_tcp_get_hdr(packet); if (ip_header) { struct in_addr *target; if (src_or_dst == src) { target = (struct in_addr *) &ip_header->saddr; } else if (src_or_dst == dst) { target = (struct in_addr *) &ip_header->daddr; } inet_aton(target_ip_address, target); nfq_ip_set_checksum(ip_header); nfq_tcp_compute_checksum_ipv4(tcp_header, ip_header); memcpy(packet_data, pktb_data(packet), packet_length); } pktb_free(packet); return nfq_set_verdict(q, id, NF_ACCEPT, packet_length, packet_data); }