libnetfilter_queue  1.0.3
ipv4.c
1 /*
2  * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This code has been sponsored by Vyatta Inc. <http://www.vyatta.com>
10  */
11 
12 #include <stdio.h>
13 #include <stdbool.h>
14 #include <arpa/inet.h>
15 #include <netinet/ip.h>
16 
17 #include <libnetfilter_queue/libnetfilter_queue.h>
18 #include <libnetfilter_queue/libnetfilter_queue_ipv4.h>
19 #include <libnetfilter_queue/pktbuff.h>
20 
21 #include "internal.h"
22 
35 struct iphdr *nfq_ip_get_hdr(struct pkt_buff *pktb)
36 {
37  struct iphdr *iph;
38  unsigned int pktlen = pktb->tail - pktb->network_header;
39 
40  /* Not enough room for IPv4 header. */
41  if (pktlen < sizeof(struct iphdr))
42  return NULL;
43 
44  iph = (struct iphdr *)pktb->network_header;
45 
46  /* Not IPv4 packet. */
47  if (iph->version != 4)
48  return NULL;
49 
50  /* Malformed IPv4 total length field. */
51  if (ntohs(iph->tot_len) > pktlen)
52  return NULL;
53 
54  return iph;
55 }
56 EXPORT_SYMBOL(nfq_ip_get_hdr);
57 
63 int nfq_ip_set_transport_header(struct pkt_buff *pktb, struct iphdr *iph)
64 {
65  int doff = iph->ihl * 4;
66 
67  /* Wrong offset to IPv4 payload. */
68  if ((int)pktb->len - doff <= 0)
69  return -1;
70 
71  pktb->transport_header = pktb->network_header + doff;
72  return 0;
73 }
74 EXPORT_SYMBOL(nfq_ip_set_transport_header);
75 
83 void nfq_ip_set_checksum(struct iphdr *iph)
84 {
85  uint32_t iph_len = iph->ihl * 4;
86 
87  iph->check = 0;
88  iph->check = nfq_checksum(0, (uint16_t *)iph, iph_len);
89 }
90 EXPORT_SYMBOL(nfq_ip_set_checksum);
91 
103 int nfq_ip_mangle(struct pkt_buff *pkt, unsigned int dataoff,
104  unsigned int match_offset, unsigned int match_len,
105  const char *rep_buffer, unsigned int rep_len)
106 {
107  struct iphdr *iph = (struct iphdr *) pkt->network_header;
108 
109  if (!pktb_mangle(pkt, dataoff, match_offset, match_len,
110  rep_buffer, rep_len))
111  return 0;
112 
113  /* fix IP hdr checksum information */
114  iph->tot_len = htons(pkt->len);
115  nfq_ip_set_checksum(iph);
116 
117  return 1;
118 }
119 EXPORT_SYMBOL(nfq_ip_mangle);
120 
131 int nfq_ip_snprintf(char *buf, size_t size, const struct iphdr *iph)
132 {
133  int ret;
134  struct in_addr src = { iph->saddr };
135  struct in_addr dst = { iph->daddr };
136 
137  char src_str[INET_ADDRSTRLEN];
138  char dst_str[INET_ADDRSTRLEN];
139 
140  ret = snprintf(buf, size, "SRC=%s DST=%s LEN=%u TOS=0x%X "
141  "PREC=0x%X TTL=%u ID=%u PROTO=%u ",
142  inet_ntop(AF_INET, &src, src_str, INET_ADDRSTRLEN),
143  inet_ntop(AF_INET, &dst, dst_str, INET_ADDRSTRLEN),
144  ntohs(iph->tot_len), IPTOS_TOS(iph->tos),
145  IPTOS_PREC(iph->tos), iph->ttl, ntohs(iph->id),
146  iph->protocol);
147 
148  return ret;
149 }
150 EXPORT_SYMBOL(nfq_ip_snprintf);
151 
void nfq_ip_set_checksum(struct iphdr *iph)
Definition: ipv4.c:83
int nfq_ip_set_transport_header(struct pkt_buff *pktb, struct iphdr *iph)
Definition: ipv4.c:63
struct iphdr * nfq_ip_get_hdr(struct pkt_buff *pktb)
Definition: ipv4.c:35
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)
Definition: ipv4.c:103
int nfq_ip_snprintf(char *buf, size_t size, const struct iphdr *iph)
Definition: ipv4.c:131