2 * netsniff-ng - the packet sniffing beast
3 * Subject to the GPL, version 2.
8 #include <netinet/in.h>
9 #include <net/ethernet.h>
11 #include "trafgen_l2.h"
12 #include "trafgen_l3.h"
13 #include "trafgen_l4.h"
14 #include "trafgen_proto.h"
15 #include "trafgen_dump.h"
17 #define DUMP(fmt, ...) fprintf((ctx)->file, fmt, ##__VA_ARGS__)
19 #define PKT_START() DUMP("{\n")
20 #define PKT_END() DUMP("}\n")
22 #define HDR_START(h) DUMP(" %s(", h)
23 #define HDR_END(h) DUMP(" ),\n")
25 #define FIELD_START(fmt, ...) DUMP(fmt",\n", ##__VA_ARGS__)
26 #define FIELD_END(fmt, ...) DUMP(" "fmt"\n", ##__VA_ARGS__)
27 #define FIELD(fmt, ...) DUMP(" "fmt",\n", ##__VA_ARGS__)
33 static int proto_dump_eth(struct dump_ctx
*ctx
, struct proto_hdr
*hdr
)
39 mac
= proto_hdr_field_get_bytes(hdr
, ETH_DST_ADDR
);
40 FIELD_START("da=%02x:%02x:%02x:%02x:%02x:%02x",
41 mac
[0], mac
[1], mac
[2], mac
[3], mac
[4], mac
[5]);
43 mac
= proto_hdr_field_get_bytes(hdr
, ETH_SRC_ADDR
);
44 FIELD("sa=%02x:%02x:%02x:%02x:%02x:%02x",
45 mac
[0], mac
[1], mac
[2], mac
[3], mac
[4], mac
[5]);
47 FIELD_END("type=0x%x", proto_hdr_field_get_u16(hdr
, ETH_TYPE
));
53 static int proto_dump_vlan(struct dump_ctx
*ctx
, struct proto_hdr
*hdr
)
57 FIELD_START("id=%d", proto_hdr_field_get_u16(hdr
, VLAN_VID
));
58 FIELD("pcp=%d", proto_hdr_field_get_u16(hdr
, VLAN_PCP
));
59 FIELD("dei=%d", proto_hdr_field_get_u16(hdr
, VLAN_DEI
));
60 FIELD_END("tpid=0x%x", proto_hdr_field_get_u16(hdr
, VLAN_TPID
));
66 static int proto_dump_arp(struct dump_ctx
*ctx
, struct proto_hdr
*hdr
)
68 char ip_str
[INET_ADDRSTRLEN
];
75 mac
= proto_hdr_field_get_bytes(hdr
, ARP_SHA
);
76 FIELD_START("smac=%02x:%02x:%02x:%02x:%02x:%02x",
77 mac
[0], mac
[1], mac
[2], mac
[3], mac
[4], mac
[5]);
79 ip
= proto_hdr_field_get_be32(hdr
, ARP_SPA
);
80 inet_ntop(AF_INET
, &ip
, ip_str
, sizeof(ip_str
));
81 FIELD("sip=%s", ip_str
);
83 mac
= proto_hdr_field_get_bytes(hdr
, ARP_THA
);
84 FIELD("tmac=%02x:%02x:%02x:%02x:%02x:%02x",
85 mac
[0], mac
[1], mac
[2], mac
[3], mac
[4], mac
[5]);
87 ip
= proto_hdr_field_get_be32(hdr
, ARP_TPA
);
88 inet_ntop(AF_INET
, &ip
, ip_str
, sizeof(ip_str
));
89 FIELD("tip=%s", ip_str
);
91 oper
= proto_hdr_field_get_u16(hdr
, ARP_OPER
);
93 if (oper
== ARPOP_REQUEST
)
94 FIELD_END("op=request");
95 else if (oper
== ARPOP_REPLY
)
96 FIELD_END("op=reply");
98 FIELD_END("op=0x%x", oper
);
104 static int proto_dump_ip4(struct dump_ctx
*ctx
, struct proto_hdr
*hdr
)
106 char ip_sa_str
[INET_ADDRSTRLEN
];
107 char ip_da_str
[INET_ADDRSTRLEN
];
110 ip
= proto_hdr_field_get_be32(hdr
, IP4_SADDR
);
111 inet_ntop(AF_INET
, &ip
, ip_sa_str
, sizeof(ip_sa_str
));
113 ip
= proto_hdr_field_get_be32(hdr
, IP4_DADDR
);
114 inet_ntop(AF_INET
, &ip
, ip_da_str
, sizeof(ip_da_str
));
118 FIELD_START("ver=0x%x", proto_hdr_field_get_u8(hdr
, IP4_VER
));
119 FIELD("ihl=0x%x", proto_hdr_field_get_u8(hdr
, IP4_IHL
));
120 FIELD("dscp=0x%x", proto_hdr_field_get_u8(hdr
, IP4_DSCP
));
121 FIELD("ecn=0x%x", proto_hdr_field_get_u8(hdr
, IP4_ECN
));
122 FIELD("tos=0x%x", proto_hdr_field_get_u8(hdr
, IP4_TOS
));
123 FIELD("len=%d", proto_hdr_field_get_u16(hdr
, IP4_LEN
));
124 FIELD("id=0x%x", proto_hdr_field_get_u16(hdr
, IP4_ID
));
125 FIELD("flags=0x%x", proto_hdr_field_get_u16(hdr
, IP4_FLAGS
));
126 if (proto_hdr_field_get_u16(hdr
, IP4_MF
))
128 if (proto_hdr_field_get_u16(hdr
, IP4_DF
))
130 FIELD("frag=0x%x", proto_hdr_field_get_u16(hdr
, IP4_FRAG_OFFS
));
131 FIELD("ttl=%d", proto_hdr_field_get_u8(hdr
, IP4_TTL
));
132 FIELD("proto=0x%x", proto_hdr_field_get_u8(hdr
, IP4_PROTO
));
133 FIELD("csum=0x%x", proto_hdr_field_get_u16(hdr
, IP4_CSUM
));
134 FIELD("sa=%s", ip_sa_str
);
135 FIELD_END("da=%s", ip_da_str
);
141 static int proto_dump_udp(struct dump_ctx
*ctx
, struct proto_hdr
*hdr
)
145 FIELD_START("dp=%d", proto_hdr_field_get_u16(hdr
, UDP_SPORT
));
146 FIELD("sp=%d", proto_hdr_field_get_u16(hdr
, UDP_DPORT
));
147 FIELD("len=%d", proto_hdr_field_get_u16(hdr
, UDP_LEN
));
148 FIELD_END("csum=0x%x", proto_hdr_field_get_u16(hdr
, UDP_CSUM
));
154 static int proto_dump_tcp(struct dump_ctx
*ctx
, struct proto_hdr
*hdr
)
158 FIELD_START("dp=%d", proto_hdr_field_get_u16(hdr
, TCP_SPORT
));
159 FIELD("sp=%d", proto_hdr_field_get_u16(hdr
, TCP_DPORT
));
160 FIELD("seq=0x%x", proto_hdr_field_get_u32(hdr
, TCP_SEQ
));
161 FIELD("ackseq=0x%x", proto_hdr_field_get_u32(hdr
, TCP_ACK_SEQ
));
162 FIELD("hlen=%d", proto_hdr_field_get_u16(hdr
, TCP_DOFF
));
163 if (proto_hdr_field_get_u16(hdr
, TCP_CWR
))
165 if (proto_hdr_field_get_u16(hdr
, TCP_ECE
))
167 if (proto_hdr_field_get_u16(hdr
, TCP_URG
))
169 if (proto_hdr_field_get_u16(hdr
, TCP_ACK
))
171 if (proto_hdr_field_get_u16(hdr
, TCP_PSH
))
173 if (proto_hdr_field_get_u16(hdr
, TCP_RST
))
175 if (proto_hdr_field_get_u16(hdr
, TCP_SYN
))
177 if (proto_hdr_field_get_u16(hdr
, TCP_FIN
))
179 FIELD("win=%d", proto_hdr_field_get_u16(hdr
, TCP_WINDOW
));
180 FIELD("csum=0x%x", proto_hdr_field_get_u16(hdr
, TCP_CSUM
));
181 FIELD_END("urgptr=0x%x", proto_hdr_field_get_u16(hdr
, TCP_URG_PTR
));
187 static int proto_dump_hdr(struct dump_ctx
*ctx
, struct proto_hdr
*hdr
)
189 switch (hdr
->ops
->id
) {
191 return proto_dump_eth(ctx
, hdr
);
193 return proto_dump_vlan(ctx
, hdr
);
195 return proto_dump_arp(ctx
, hdr
);
197 return proto_dump_ip4(ctx
, hdr
);
199 return proto_dump_udp(ctx
, hdr
);
201 return proto_dump_tcp(ctx
, hdr
);
207 int packet_dump_fd(struct packet
*pkt
, int fd
)
209 struct proto_hdr
*hdr
;
211 struct dump_ctx _ctx
;
212 struct dump_ctx
*ctx
= &_ctx
;
216 _ctx
.file
= fdopen(fd
, "w");
220 /* handle case if there is already proto headers */
221 if (pkt
->headers_count
== 0) {
222 hdr
= proto_packet_apply(PROTO_ETH
, pkt
);
224 while ((pid
= proto_hdr_get_next_proto(hdr
)) != __PROTO_MAX
) {
225 if (hdr
->pkt_offset
+ hdr
->len
>= pkt
->len
)
228 hdr
= proto_packet_apply(pid
, pkt
);
233 for (i
= 0; i
< pkt
->headers_count
; i
++) {
234 hdr
= pkt
->headers
[i
];
236 if (proto_dump_hdr(ctx
, hdr
))
239 dump_len
+= hdr
->len
;
242 /* print rest as a bytes */
243 if (dump_len
< pkt
->len
) {
247 for (i
= dump_len
; i
< pkt
->len
; ++i
, ++j
) {
250 DUMP("0x%02x,", pkt
->payload
[i
]);