2 * netsniff-ng - the packet sniffing beast
3 * Subject to the GPL, version 2.
7 #include <netinet/in.h>
12 #include "trafgen_l3.h"
13 #include "trafgen_l4.h"
14 #include "trafgen_conf.h"
15 #include "trafgen_proto.h"
17 static struct proto_field udp_fields
[] = {
18 { .id
= UDP_SPORT
, .len
= 2, .offset
= 0 },
19 { .id
= UDP_DPORT
, .len
= 2, .offset
= 2 },
20 { .id
= UDP_LEN
, .len
= 2, .offset
= 4 },
21 { .id
= UDP_CSUM
, .len
= 2, .offset
= 6 },
24 static void udp_header_init(struct proto_hdr
*hdr
)
26 proto_lower_default_add(hdr
, PROTO_IP4
);
28 proto_header_fields_add(hdr
, udp_fields
, array_size(udp_fields
));
31 static void udp_packet_finish(struct proto_hdr
*hdr
)
33 struct proto_hdr
*lower
= proto_lower_header(hdr
);
34 struct packet
*pkt
= current_packet();
38 total_len
= pkt
->len
- hdr
->pkt_offset
;
39 proto_field_set_default_be16(hdr
, UDP_LEN
, total_len
);
41 if (proto_field_is_set(hdr
, UDP_CSUM
))
49 csum
= p4_csum((void *) proto_header_ptr(lower
), proto_header_ptr(hdr
),
50 total_len
, IPPROTO_UDP
);
53 csum
= p6_csum((void *) proto_header_ptr(lower
), proto_header_ptr(hdr
),
54 total_len
, IPPROTO_UDP
);
61 proto_field_set_be16(hdr
, UDP_CSUM
, bswap_16(csum
));
64 static struct proto_hdr udp_hdr
= {
67 .header_init
= udp_header_init
,
68 .packet_finish
= udp_packet_finish
,
71 static struct proto_field tcp_fields
[] = {
72 { .id
= TCP_SPORT
, .len
= 2, .offset
= 0 },
73 { .id
= TCP_DPORT
, .len
= 2, .offset
= 2 },
74 { .id
= TCP_SEQ
, .len
= 4, .offset
= 4 },
75 { .id
= TCP_ACK_SEQ
, .len
= 4, .offset
= 8 },
76 { .id
= TCP_DOFF
, .len
= 2, .offset
= 12, .shift
= 12, .mask
= 0xf000 },
77 /* reserved (4 bits) */
78 { .id
= TCP_CWR
, .len
= 2, .offset
= 12, .shift
= 7, .mask
= 0x0080 },
79 { .id
= TCP_ECE
, .len
= 2, .offset
= 12, .shift
= 6, .mask
= 0x0040 },
80 { .id
= TCP_URG
, .len
= 2, .offset
= 12, .shift
= 5, .mask
= 0x0020 },
81 { .id
= TCP_ACK
, .len
= 2, .offset
= 12, .shift
= 4, .mask
= 0x0010 },
82 { .id
= TCP_PSH
, .len
= 2, .offset
= 12, .shift
= 3, .mask
= 0x0008 },
83 { .id
= TCP_RST
, .len
= 2, .offset
= 12, .shift
= 2, .mask
= 0x0004 },
84 { .id
= TCP_SYN
, .len
= 2, .offset
= 12, .shift
= 1, .mask
= 0x0002 },
85 { .id
= TCP_FIN
, .len
= 2, .offset
= 12, .shift
= 0, .mask
= 0x0001 },
86 { .id
= TCP_WINDOW
, .len
= 2, .offset
= 14 },
87 { .id
= TCP_CSUM
, .len
= 2, .offset
= 16 },
88 { .id
= TCP_URG_PTR
, .len
= 2, .offset
= 18 },
91 static void tcp_header_init(struct proto_hdr
*hdr
)
93 proto_lower_default_add(hdr
, PROTO_IP4
);
95 proto_header_fields_add(hdr
, tcp_fields
, array_size(tcp_fields
));
97 proto_field_set_default_be16(hdr
, TCP_DOFF
, 5);
100 static void tcp_packet_finish(struct proto_hdr
*hdr
)
102 struct proto_hdr
*lower
= proto_lower_header(hdr
);
103 struct packet
*pkt
= current_packet();
107 if (proto_field_is_set(hdr
, TCP_CSUM
))
113 total_len
= pkt
->len
- hdr
->pkt_offset
;
117 csum
= p4_csum((void *) proto_header_ptr(lower
), proto_header_ptr(hdr
),
118 total_len
, IPPROTO_TCP
);
121 csum
= p6_csum((void *) proto_header_ptr(lower
), proto_header_ptr(hdr
),
122 total_len
, IPPROTO_TCP
);
129 proto_field_set_be16(hdr
, TCP_CSUM
, bswap_16(csum
));
132 static struct proto_hdr tcp_hdr
= {
135 .header_init
= tcp_header_init
,
136 .packet_finish
= tcp_packet_finish
,
139 static struct proto_field icmpv4_fields
[] = {
140 { .id
= ICMPV4_TYPE
, .len
= 1, .offset
= 0 },
141 { .id
= ICMPV4_CODE
, .len
= 1, .offset
= 1 },
142 { .id
= ICMPV4_CSUM
, .len
= 2, .offset
= 2 },
143 /* Echo/Ping fields */
144 { .id
= ICMPV4_ID
, .len
= 2, .offset
= 4 },
145 { .id
= ICMPV4_SEQ
, .len
= 2, .offset
= 6 },
147 { .id
= ICMPV4_REDIR_ADDR
, .len
= 4, .offset
= 4 },
149 { .id
= ICMPV4_MTU
, .len
= 2, .offset
= 6 },
152 static void icmpv4_header_init(struct proto_hdr
*hdr
)
154 proto_lower_default_add(hdr
, PROTO_IP4
);
156 proto_header_fields_add(hdr
, icmpv4_fields
, array_size(icmpv4_fields
));
159 static void icmpv4_packet_finish(struct proto_hdr
*hdr
)
164 if (proto_field_is_set(hdr
, ICMPV4_CSUM
))
167 pkt
= current_packet();
169 csum
= htons(calc_csum(proto_header_ptr(hdr
), pkt
->len
- hdr
->pkt_offset
));
170 proto_field_set_u16(hdr
, ICMPV4_CSUM
, bswap_16(csum
));
173 static struct proto_hdr icmpv4_hdr
= {
176 .header_init
= icmpv4_header_init
,
177 .packet_finish
= icmpv4_packet_finish
,
180 static struct proto_field icmpv6_fields
[] = {
181 { .id
= ICMPV6_TYPE
, .len
= 1, .offset
= 0 },
182 { .id
= ICMPV6_CODE
, .len
= 1, .offset
= 1 },
183 { .id
= ICMPV6_CSUM
, .len
= 2, .offset
= 2 }
186 static void icmpv6_header_init(struct proto_hdr
*hdr
)
188 proto_lower_default_add(hdr
, PROTO_IP6
);
190 proto_header_fields_add(hdr
, icmpv6_fields
, array_size(icmpv6_fields
));
193 static void icmpv6_packet_finish(struct proto_hdr
*hdr
)
195 struct proto_hdr
*lower
= proto_lower_header(hdr
);
196 struct packet
*pkt
= current_packet();
200 if (proto_field_is_set(hdr
, ICMPV6_CSUM
))
206 total_len
= pkt
->len
- hdr
->pkt_offset
;
210 csum
= p6_csum((void *) proto_header_ptr(lower
), proto_header_ptr(hdr
),
211 total_len
, IPPROTO_ICMPV6
);
218 proto_field_set_be16(hdr
, ICMPV6_CSUM
, bswap_16(csum
));
221 static struct proto_hdr icmpv6_hdr
= {
224 .header_init
= icmpv6_header_init
,
225 .packet_finish
= icmpv6_packet_finish
,
228 void protos_l4_init(void)
230 proto_header_register(&udp_hdr
);
231 proto_header_register(&tcp_hdr
);
232 proto_header_register(&icmpv4_hdr
);
233 proto_header_register(&icmpv6_hdr
);