2 * netsniff-ng - the packet sniffing beast
3 * Subject to the GPL, version 2.
8 #include <linux/if_ether.h>
12 #include "trafgen_conf.h"
13 #include "trafgen_l2.h"
14 #include "trafgen_proto.h"
16 #define field_shift_and_mask(f, v) (((v) << (f)->shift) & \
17 ((f)->mask ? (f)->mask : (0xffffffff)))
19 #define field_unmask_and_unshift(f, v) (((v) & \
20 ((f)->mask ? (f)->mask : (0xffffffff))) >> (f)->shift)
22 static struct proto_ctx ctx
;
24 #define PROTO_MAX_LAYERS 16
26 static struct proto_hdr
*headers
[PROTO_MAX_LAYERS
];
27 static size_t headers_count
;
29 static struct proto_hdr
*registered
;
31 struct proto_hdr
*proto_current_header(void)
33 if (headers_count
> 0)
34 return headers
[headers_count
- 1];
36 panic("No header was added\n");
39 struct proto_hdr
*proto_lower_header(struct proto_hdr
*hdr
)
41 struct proto_hdr
*lower
= NULL
;
44 if (headers_count
== 0)
47 for (i
= 1, lower
= headers
[0]; i
< headers_count
; i
++) {
48 if (headers
[i
] == hdr
)
49 return headers
[i
- 1];
55 uint8_t *proto_header_ptr(struct proto_hdr
*hdr
)
57 return ¤t_packet()->payload
[hdr
->pkt_offset
];
60 static struct proto_hdr
*proto_header_by_id(enum proto_id id
)
62 struct proto_hdr
*p
= registered
;
64 for (; p
; p
= p
->next
)
68 panic("Can't lookup proto by id %u\n", id
);
71 void proto_header_register(struct proto_hdr
*hdr
)
73 hdr
->next
= registered
;
77 hdr
->fields_count
= 0;
80 static void proto_fields_realloc(struct proto_hdr
*hdr
, size_t count
)
82 hdr
->fields
= xrealloc(hdr
->fields
, count
* sizeof(*hdr
->fields
));
83 hdr
->fields_count
= count
;
86 void proto_header_fields_add(struct proto_hdr
*hdr
, struct proto_field
*fields
,
89 struct packet
*pkt
= current_packet();
90 struct proto_field
*f
;
94 hdr
->pkt_offset
= pkt
->len
;
96 proto_fields_realloc(hdr
, hdr
->fields_count
+ count
);
98 for (i
= 0; count
>= 1; count
--, i
++) {
99 f
= &hdr
->fields
[hdr
->fields_count
- count
];
101 f
->id
= fields
[i
].id
;
102 f
->len
= fields
[i
].len
;
104 f
->shift
= fields
[i
].shift
;
105 f
->mask
= fields
[i
].mask
;
106 f
->pkt_offset
= hdr
->pkt_offset
+ fields
[i
].offset
;
108 if (f
->pkt_offset
+ f
->len
> pkt
->len
)
109 set_fill(0, (f
->pkt_offset
+ f
->len
) - pkt
->len
);
113 static struct proto_field
*proto_field_by_id(struct proto_hdr
*hdr
, uint32_t fid
)
117 for (i
= 0; i
< hdr
->fields_count
; i
++)
118 if (hdr
->fields
[i
].id
== fid
)
119 return &hdr
->fields
[i
];
121 panic("Failed lookup field id %u for proto id %u\n", fid
, hdr
->id
);
124 bool proto_field_is_set(struct proto_hdr
*hdr
, uint32_t fid
)
126 struct proto_field
*field
= proto_field_by_id(hdr
, fid
);
128 return field
? field
->is_set
: false;
131 void proto_header_init(enum proto_id pid
)
133 struct proto_hdr
*hdr
= proto_header_by_id(pid
);
134 struct proto_hdr
*new_hdr
;
136 if (headers_count
>= PROTO_MAX_LAYERS
)
137 panic("Too many proto headers\n");
139 new_hdr
= xmalloc(sizeof(*new_hdr
));
140 memcpy(new_hdr
, hdr
, sizeof(*new_hdr
));
142 if (new_hdr
->header_init
)
143 new_hdr
->header_init(new_hdr
);
145 headers
[headers_count
++] = new_hdr
;
148 void proto_header_finish(struct proto_hdr
*hdr
)
150 if (hdr
&& hdr
->header_finish
)
151 hdr
->header_finish(hdr
);
154 void proto_lower_default_add(enum proto_id pid
)
156 if (headers_count
> 0) {
157 if (proto_current_header()->layer
>= proto_header_by_id(pid
)->layer
)
159 if (proto_current_header()->id
== pid
)
163 proto_header_init(pid
);
166 static void __proto_field_set_bytes(struct proto_hdr
*hdr
, uint32_t fid
,
167 uint8_t *bytes
, bool is_default
, bool is_be
)
169 struct proto_field
*field
;
175 field
= proto_field_by_id(hdr
, fid
);
177 if (is_default
&& field
->is_set
)
180 payload
= ¤t_packet()->payload
[field
->pkt_offset
];
182 if (field
->len
== 1) {
183 v8
= field_shift_and_mask(field
, *bytes
);
184 v8
= field
->mask
? (v8
| *payload
) : v8
;
186 } else if (field
->len
== 2) {
187 v16
= field_shift_and_mask(field
, *(uint16_t *)bytes
);
188 v16
= is_be
? cpu_to_be16(v16
) : v16
;
189 v16
= field
->mask
? (v16
| *(uint16_t *)payload
) : v16
;
190 bytes
= (uint8_t *)&v16
;
191 } else if (field
->len
== 4) {
192 v32
= field_shift_and_mask(field
, *(uint32_t *)bytes
);
193 v32
= is_be
? cpu_to_be32(v32
) : v32
;
194 v32
= field
->mask
? (v32
| *(uint32_t *)payload
) : v32
;
195 bytes
= (uint8_t *)&v32
;
198 memcpy(payload
, bytes
, field
->len
);
201 field
->is_set
= true;
204 void proto_field_set_bytes(struct proto_hdr
*hdr
, uint32_t fid
, uint8_t *bytes
)
206 __proto_field_set_bytes(hdr
, fid
, bytes
, false, false);
209 static uint8_t *__proto_field_get_bytes(struct proto_field
*field
)
211 struct packet
*pkt
= current_packet();
213 return &pkt
->payload
[field
->pkt_offset
];
216 void proto_field_set_u8(struct proto_hdr
*hdr
, uint32_t fid
, uint8_t val
)
218 proto_field_set_bytes(hdr
, fid
, (uint8_t *)&val
);
221 uint8_t proto_field_get_u8(struct proto_hdr
*hdr
, uint32_t fid
)
223 struct proto_field
*field
= proto_field_by_id(hdr
, fid
);
224 uint8_t val
= *__proto_field_get_bytes(field
);
226 return field_unmask_and_unshift(field
, val
);
229 void proto_field_set_u16(struct proto_hdr
*hdr
, uint32_t fid
, uint16_t val
)
231 proto_field_set_bytes(hdr
, fid
, (uint8_t *)&val
);
234 uint16_t proto_field_get_u16(struct proto_hdr
*hdr
, uint32_t fid
)
236 struct proto_field
*field
= proto_field_by_id(hdr
, fid
);
237 uint16_t val
= *(uint16_t *)__proto_field_get_bytes(field
);
239 return field_unmask_and_unshift(field
, be16_to_cpu(val
));
242 void proto_field_set_u32(struct proto_hdr
*hdr
, uint32_t fid
, uint32_t val
)
244 proto_field_set_bytes(hdr
, fid
, (uint8_t *)&val
);
247 uint32_t proto_field_get_u32(struct proto_hdr
*hdr
, uint32_t fid
)
249 struct proto_field
*field
= proto_field_by_id(hdr
, fid
);
250 uint32_t val
= *(uint32_t *)__proto_field_get_bytes(field
);
252 return field_unmask_and_unshift(field
, be32_to_cpu(val
));
255 void proto_field_set_default_bytes(struct proto_hdr
*hdr
, uint32_t fid
, uint8_t *bytes
)
257 __proto_field_set_bytes(hdr
, fid
, bytes
, true, false);
260 void proto_field_set_default_u8(struct proto_hdr
*hdr
, uint32_t fid
, uint8_t val
)
262 __proto_field_set_bytes(hdr
, fid
, (uint8_t *)&val
, true, false);
265 void proto_field_set_default_u16(struct proto_hdr
*hdr
, uint32_t fid
, uint16_t val
)
267 __proto_field_set_bytes(hdr
, fid
, (uint8_t *)&val
, true, false);
270 void proto_field_set_default_u32(struct proto_hdr
*hdr
, uint32_t fid
, uint32_t val
)
272 __proto_field_set_bytes(hdr
, fid
, (uint8_t *)&val
, true, false);
275 void proto_field_set_be16(struct proto_hdr
*hdr
, uint32_t fid
, uint16_t val
)
277 __proto_field_set_bytes(hdr
, fid
, (uint8_t *)&val
, false, true);
280 void proto_field_set_be32(struct proto_hdr
*hdr
, uint32_t fid
, uint32_t val
)
282 __proto_field_set_bytes(hdr
, fid
, (uint8_t *)&val
, false, true);
285 void proto_field_set_default_be16(struct proto_hdr
*hdr
, uint32_t fid
, uint16_t val
)
287 __proto_field_set_bytes(hdr
, fid
, (uint8_t *)&val
, true, true);
290 void proto_field_set_default_be32(struct proto_hdr
*hdr
, uint32_t fid
, uint32_t val
)
292 __proto_field_set_bytes(hdr
, fid
, (uint8_t *)&val
, true, true);
295 static void __proto_field_set_dev_mac(struct proto_hdr
*hdr
, uint32_t fid
,
298 uint8_t mac
[ETH_ALEN
];
301 if (proto_field_is_set(hdr
, fid
))
305 panic("Device is not specified\n");
307 ret
= device_hw_address(hdr
->ctx
->dev
, mac
, sizeof(mac
));
309 panic("Could not get device hw address\n");
311 __proto_field_set_bytes(hdr
, fid
, mac
, is_default
, false);
314 void proto_field_set_dev_mac(struct proto_hdr
*hdr
, uint32_t fid
)
316 __proto_field_set_dev_mac(hdr
, fid
, false);
319 void proto_field_set_default_dev_mac(struct proto_hdr
*hdr
, uint32_t fid
)
321 __proto_field_set_dev_mac(hdr
, fid
, true);
324 void protos_init(const char *dev
)
332 for (p
= registered
; p
; p
= p
->next
)
336 void proto_packet_finish(void)
340 /* Go down from upper layers to do last calculations (checksum) */
341 for (i
= headers_count
- 1; i
>= 0; i
--) {
342 struct proto_hdr
*p
= headers
[i
];
344 if (p
->packet_finish
)
348 for (i
= 0; i
< headers_count
; i
++) {
349 struct proto_hdr
*p
= headers
[i
];