sk_buff问题
想问一下sk_buff中的data包不包括各种协议的数据包头?我看snort中通过调用pcap_loop->recvfrom只是把协议站中sk_buff结构
中的data指针所指的区域拷贝到用户空间了,它是怎样统计出各种类型的
数据包的呢?除非data所指的区域包括完整的协议包头.
请高手指点,不胜感激
129 struct sk_buff {
130 /* These two members must be first. */
131 struct sk_buff* next; /* Next buffer in list */
132 struct sk_buff* prev; /* Previous buffer in list */
133
134 struct sk_buff_head * list; /* List we are on */
135 struct sock *sk; /* Socket we are owned by */
136 struct timevalstamp; /* Time we arrived */
137 struct net_device *dev; /* Device we arrived on/are leaving by */
138
139 /* Transport layer header */
140 union
141 {
142 struct tcphdr *th;
143 struct udphdr *uh;
144 struct icmphdr*icmph;
145 struct igmphdr*igmph;
146 struct iphdr *ipiph;
147 struct spxhdr *spxh;
148 unsigned char *raw;
149 } h;
150
151 /* Network layer header */
152 union
153 {
154 struct iphdr *iph;
155 struct ipv6hdr*ipv6h;
156 struct arphdr *arph;
157 struct ipxhdr *ipxh;
158 unsigned char *raw;
159 } nh;
160
161 /* Link layer header */
162 union
163 {
164 struct ethhdr *ethernet;
165 unsigned char *raw;
166 } mac;
167
168 structdst_entry *dst;
169
170 /*
171 * This is the control buffer. It is free to use for every
172 * layer. Please put your private variables there. If you
173 * want to keep them across layers you have to do a skb_clone()
174 * first. This is owned by whoever has the skb queued ATM.
175 */
176 char cb[48];
177
178 unsigned int len; /* Length of actual data */
179 unsigned int data_len;
180 unsigned int csum; /* Checksum */
181 unsigned char __unused, /* Dead field, may be reused */
182 cloned, /* head may be cloned (check refcnt to be sure). */
183 pkt_type, /* Packet class */
184 ip_summed; /* Driver fed us an IP checksum */
185 __u32 priority; /* Packet queueing priority */
186 atomic_t users; /* User count - see datagram.c,tcp.c */
187 unsigned shortprotocol; /* Packet protocol from driver. */
188 unsigned shortsecurity; /* Security level of packet */
189 unsigned int truesize; /* Buffer size */
190
191 unsigned char *head; /* Head of buffer */
192 unsigned char *data; /* Data head pointer */
193 unsigned char *tail; /* Tail pointer */
194 unsigned char *end; /* End pointer */
195
196 void (*destructor)(struct sk_buff *); /* Destruct function */
197 #ifdef CONFIG_NETFILTER
198 /* Can be used for communication between hooks. */
199 unsigned long nfmark;
200 /* Cache info */
201 __u32 nfcache;
202 /* Associated connection, if any */
203 struct nf_ct_info *nfct;
204 #ifdef CONFIG_NETFILTER_DEBUG
205 unsigned int nf_debug;
206 #endif
207 #endif /*CONFIG_NETFILTER*/
208
209 #if defined(CONFIG_HIPPI)
210 union{
211 __u32 ifield;
212 } private;
213 #endif
214
215 #ifdef CONFIG_NET_SCHED
216 __u32 tc_index; /* traffic control index */
217 #endif
218 };
that data includes all info. i am checking the code where it alloc space for data check the*alloc_skb() in net/core/skbuff.c
164 struct sk_buff *alloc_skb(unsigned int size,int gfp_mask)
165 {
166 struct sk_buff *skb;
167 u8 *data;
168
169 if (in_interrupt() && (gfp_mask & __GFP_WAIT)) {
170 static int count = 0;
171 if (++count < 5) {
172 printk(KERN_ERR "alloc_skb called nonatomically "
173 "from interrupt %p\n", NET_CALLER(size));
174 BUG();
175 }
176 gfp_mask &= ~__GFP_WAIT;
177 }
178
179 /* Get the HEAD */
180 skb = skb_head_from_pool();
181 if (skb == NULL) {
182 skb = kmem_cache_alloc(skbuff_head_cache, gfp_mask & ~__GFP_DMA);
183 if (skb == NULL)
184 goto nohead;
185 }
186
187 /* Get the DATA. Size must match skb_add_mtu(). */
188 size = SKB_DATA_ALIGN(size);
189 data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
190 if (data == NULL)
191 goto nodata;
192
193 /* XXX: does not include slab overhead */
194 skb->truesize = size + sizeof(struct sk_buff);
195
196 /* Load the data pointers. */
197 skb->head = data;
198 skb->data = data;
199 skb->tail = data;
200 skb->end = data + size;
201
202 /* Set up other state */
203 skb->len = 0;
204 skb->cloned = 0;
205 skb->data_len = 0;
206
207 atomic_set(&skb->users, 1);
208 atomic_set(&(skb_shinfo(skb)->dataref), 1);
209 skb_shinfo(skb)->nr_frags = 0;
210 skb_shinfo(skb)->frag_list = NULL;
211 return skb;
212
213 nodata:
214 skb_head_to_pool(skb);
215 nohead:
216 return NULL;
217 }
here allocate the skb header and data. see the assignment of head, end, tail, data.
and read ip_build_xmit() in net/ipv4/ip_output.c to see after allocate a skb, how it compute the header offset and operate on it.
am i right? rfc. 在不同的协议层,skbuff的指针都要进行调整,所以data也是调整的。这些有关的函数是
static inline unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
{
skb->data-=len;
skb->len+=len;
if(skb->data<skb->head) {
skb_under_panic(skb, len, current_text_addr());
}
return skb->data;
}
static inline char *__skb_pull(struct sk_buff *skb, unsigned int len)
{
skb->len-=len;
if (skb->len < skb->data_len)
out_of_line_bug();
return skb->data+=len;
}
等
例如在linux\net\ipv4\ip_output.c中
int ip_build_and_send_pkt()
{
。。。
/* Build the IP header. */
if (opt)
iph=(struct iphdr *)skb_push(skb,sizeof(struct iphdr) + opt->optlen);
else
iph=(struct iphdr *)skb_push(skb,sizeof(struct iphdr));
/* Adjust data pointer and fill the ip header for the packet.Also we can conclude that the data contains the protocol header(IP header for example)
*
*/
iph->version= 4;
iph->ihl = 5;
iph->tos = sk->protinfo.af_inet.tos;
。。。
} yes, the book ULK2 has description on these fun
页:
[1]