1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
|
/*
* Definitions for the 'struct sk_buff' memory handlers.
*
* Authors:
* Alan Cox, <gw4pts@gw4pts.ampr.org>
* Florian La Roche, <rzsfl@rz.uni-sb.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _LINUX_SKBUFF_H
#define _LINUX_SKBUFF_H
#include <linux/malloc.h>
#include <linux/wait.h>
#include <linux/time.h>
#include <linux/config.h>
#undef CONFIG_SKB_CHECK
#define HAVE_ALLOC_SKB /* For the drivers to know */
#define FREE_READ 1
#define FREE_WRITE 0
struct sk_buff_head {
struct sk_buff * volatile next;
struct sk_buff * volatile prev;
#if CONFIG_SKB_CHECK
int magic_debug_cookie;
#endif
};
struct sk_buff {
struct sk_buff * volatile next;
struct sk_buff * volatile prev;
#if CONFIG_SKB_CHECK
int magic_debug_cookie;
#endif
struct sk_buff * volatile link3;
struct sock *sk;
volatile unsigned long when; /* used to compute rtt's */
struct timeval stamp;
struct device *dev;
struct sk_buff *mem_addr;
union {
struct tcphdr *th;
struct ethhdr *eth;
struct iphdr *iph;
struct udphdr *uh;
unsigned char *raw;
unsigned long seq;
} h;
struct iphdr *ip_hdr; /* For IPPROTO_RAW */
unsigned long mem_len;
unsigned long len;
unsigned long fraglen;
struct sk_buff *fraglist; /* Fragment list */
unsigned long truesize;
unsigned long saddr;
unsigned long daddr;
unsigned long raddr; /* next hop addr */
volatile char acked,
used,
free,
arp;
unsigned char tries,lock,localroute,pkt_type;
#define PACKET_HOST 0 /* To us */
#define PACKET_BROADCAST 1
#define PACKET_MULTICAST 2
#define PACKET_OTHERHOST 3 /* Unmatched promiscuous */
unsigned short users; /* User count - see datagram.c (and soon seqpacket.c/stream.c) */
unsigned short pkt_class; /* For drivers that need to cache the packet type with the skbuff (new PPP) */
#ifdef CONFIG_SLAVE_BALANCING
unsigned short in_dev_queue;
#endif
unsigned long padding[0];
unsigned char data[0];
};
#define SK_WMEM_MAX 32767
#define SK_RMEM_MAX 32767
#ifdef CONFIG_SKB_CHECK
#define SK_FREED_SKB 0x0DE2C0DE
#define SK_GOOD_SKB 0xDEC0DED1
#define SK_HEAD_SKB 0x12231298
#endif
#ifdef __KERNEL__
/*
* Handling routines are only of interest to the kernel
*/
#include <asm/system.h>
#if 0
extern void print_skb(struct sk_buff *);
#endif
extern void kfree_skb(struct sk_buff *skb, int rw);
extern void skb_queue_head_init(struct sk_buff_head *list);
extern void skb_queue_head(struct sk_buff_head *list,struct sk_buff *buf);
extern void skb_queue_tail(struct sk_buff_head *list,struct sk_buff *buf);
extern struct sk_buff * skb_dequeue(struct sk_buff_head *list);
extern void skb_insert(struct sk_buff *old,struct sk_buff *newsk);
extern void skb_append(struct sk_buff *old,struct sk_buff *newsk);
extern void skb_unlink(struct sk_buff *buf);
extern struct sk_buff * skb_peek_copy(struct sk_buff_head *list);
extern struct sk_buff * alloc_skb(unsigned int size, int priority);
extern void kfree_skbmem(struct sk_buff *skb, unsigned size);
extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority);
extern void skb_device_lock(struct sk_buff *skb);
extern void skb_device_unlock(struct sk_buff *skb);
extern void dev_kfree_skb(struct sk_buff *skb, int mode);
extern int skb_device_locked(struct sk_buff *skb);
/*
* Peek an sk_buff. Unlike most other operations you _MUST_
* be careful with this one. A peek leaves the buffer on the
* list and someone else may run off with it. For an interrupt
* type system cli() peek the buffer copy the data and sti();
*/
static __inline__ struct sk_buff *skb_peek(struct sk_buff_head *list_)
{
struct sk_buff *list = (struct sk_buff *)list_;
return (list->next != list)? list->next : NULL;
}
#if CONFIG_SKB_CHECK
extern int skb_check(struct sk_buff *skb,int,int, char *);
#define IS_SKB(skb) skb_check((skb), 0, __LINE__,__FILE__)
#define IS_SKB_HEAD(skb) skb_check((skb), 1, __LINE__,__FILE__)
#else
#define IS_SKB(skb)
#define IS_SKB_HEAD(skb)
extern __inline__ void skb_queue_head_init(struct sk_buff_head *list)
{
list->prev = (struct sk_buff *)list;
list->next = (struct sk_buff *)list;
}
/*
* Insert an sk_buff at the start of a list.
*/
extern __inline__ void skb_queue_head(struct sk_buff_head *list_,struct sk_buff *newsk)
{
unsigned long flags;
struct sk_buff *list = (struct sk_buff *)list_;
save_flags(flags);
cli();
newsk->next = list->next;
newsk->prev = list;
newsk->next->prev = newsk;
newsk->prev->next = newsk;
restore_flags(flags);
}
/*
* Insert an sk_buff at the end of a list.
*/
extern __inline__ void skb_queue_tail(struct sk_buff_head *list_, struct sk_buff *newsk)
{
unsigned long flags;
struct sk_buff *list = (struct sk_buff *)list_;
save_flags(flags);
cli();
newsk->next = list;
newsk->prev = list->prev;
newsk->next->prev = newsk;
newsk->prev->next = newsk;
restore_flags(flags);
}
/*
* Remove an sk_buff from a list. This routine is also interrupt safe
* so you can grab read and free buffers as another process adds them.
*/
extern __inline__ struct sk_buff *skb_dequeue(struct sk_buff_head *list_)
{
long flags;
struct sk_buff *result;
struct sk_buff *list = (struct sk_buff *)list_;
save_flags(flags);
cli();
result = list->next;
if (result == list) {
restore_flags(flags);
return NULL;
}
result->next->prev = list;
list->next = result->next;
result->next = NULL;
result->prev = NULL;
restore_flags(flags);
return result;
}
/*
* Insert a packet before another one in a list.
*/
extern __inline__ void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
{
unsigned long flags;
save_flags(flags);
cli();
newsk->next = old;
newsk->prev = old->prev;
old->prev = newsk;
newsk->prev->next = newsk;
restore_flags(flags);
}
/*
* Place a packet after a given packet in a list.
*/
extern __inline__ void skb_append(struct sk_buff *old, struct sk_buff *newsk)
{
unsigned long flags;
save_flags(flags);
cli();
newsk->prev = old;
newsk->next = old->next;
newsk->next->prev = newsk;
old->next = newsk;
restore_flags(flags);
}
/*
* Remove an sk_buff from its list. Works even without knowing the list it
* is sitting on, which can be handy at times. It also means that THE LIST
* MUST EXIST when you unlink. Thus a list must have its contents unlinked
* _FIRST_.
*/
extern __inline__ void skb_unlink(struct sk_buff *skb)
{
unsigned long flags;
save_flags(flags);
cli();
if(skb->prev && skb->next)
{
skb->next->prev = skb->prev;
skb->prev->next = skb->next;
skb->next = NULL;
skb->prev = NULL;
}
restore_flags(flags);
}
#endif
extern struct sk_buff * skb_recv_datagram(struct sock *sk,unsigned flags,int noblock, int *err);
extern int datagram_select(struct sock *sk, int sel_type, select_table *wait);
extern void skb_copy_datagram(struct sk_buff *from, int offset, char *to,int size);
extern void skb_free_datagram(struct sk_buff *skb);
#endif /* __KERNEL__ */
#endif /* _LINUX_SKBUFF_H */
|