mausezahn: use getopt_long instead of getopt
[netsniff-ng.git] / trafgen_dump.c
blobd44bf58bca2409e4b14b45a1c88a0edfb9bbf220
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Subject to the GPL, version 2.
4 */
6 #include <stdio.h>
7 #include <arpa/inet.h>
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__)
29 struct dump_ctx {
30 FILE *file;
33 static int proto_dump_eth(struct dump_ctx *ctx, struct proto_hdr *hdr)
35 uint8_t *mac;
37 HDR_START("eth");
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));
49 HDR_END();
50 return 0;
53 static int proto_dump_vlan(struct dump_ctx *ctx, struct proto_hdr *hdr)
55 HDR_START("vlan");
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));
62 HDR_END();
63 return 0;
66 static int proto_dump_arp(struct dump_ctx *ctx, struct proto_hdr *hdr)
68 char ip_str[INET_ADDRSTRLEN];
69 uint16_t oper;
70 uint8_t *mac;
71 uint32_t ip;
73 HDR_START("arp");
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");
97 else
98 FIELD_END("op=0x%x", oper);
100 HDR_END();
101 return 0;
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];
108 uint32_t ip;
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));
116 HDR_START("ip4");
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))
127 FIELD("mf");
128 if (proto_hdr_field_get_u16(hdr, IP4_DF))
129 FIELD("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);
137 HDR_END();
138 return 0;
141 static int proto_dump_ip6(struct dump_ctx *ctx, struct proto_hdr *hdr)
143 char ip_sa_str[INET6_ADDRSTRLEN];
144 char ip_da_str[INET6_ADDRSTRLEN];
145 uint8_t *ip;
147 ip = proto_hdr_field_get_bytes(hdr, IP6_SADDR);
148 inet_ntop(AF_INET6, ip, ip_sa_str, sizeof(ip_sa_str));
150 ip = proto_hdr_field_get_bytes(hdr, IP6_DADDR);
151 inet_ntop(AF_INET6, ip, ip_da_str, sizeof(ip_da_str));
153 HDR_START("ip6");
155 FIELD_START("ver=0x%x", proto_hdr_field_get_u32(hdr, IP6_VER));
156 FIELD("tc=0x%x", proto_hdr_field_get_u32(hdr, IP6_CLASS));
157 FIELD("fl=0x%x", proto_hdr_field_get_u32(hdr, IP6_FLOW_LBL));
158 FIELD("len=%d", proto_hdr_field_get_u16(hdr, IP6_LEN));
159 FIELD("nh=0x%x", proto_hdr_field_get_u8(hdr, IP6_NEXT_HDR));
160 FIELD("hl=%d", proto_hdr_field_get_u8(hdr, IP6_HOP_LIMIT));
161 FIELD("sa=%s", ip_sa_str);
162 FIELD_END("da=%s", ip_da_str);
164 HDR_END();
165 return 0;
168 static int proto_dump_udp(struct dump_ctx *ctx, struct proto_hdr *hdr)
170 HDR_START("udp");
172 FIELD_START("dp=%d", proto_hdr_field_get_u16(hdr, UDP_SPORT));
173 FIELD("sp=%d", proto_hdr_field_get_u16(hdr, UDP_DPORT));
174 FIELD("len=%d", proto_hdr_field_get_u16(hdr, UDP_LEN));
175 FIELD_END("csum=0x%x", proto_hdr_field_get_u16(hdr, UDP_CSUM));
177 HDR_END();
178 return 0;
181 static int proto_dump_tcp(struct dump_ctx *ctx, struct proto_hdr *hdr)
183 HDR_START("tcp");
185 FIELD_START("dp=%d", proto_hdr_field_get_u16(hdr, TCP_SPORT));
186 FIELD("sp=%d", proto_hdr_field_get_u16(hdr, TCP_DPORT));
187 FIELD("seq=0x%x", proto_hdr_field_get_u32(hdr, TCP_SEQ));
188 FIELD("ackseq=0x%x", proto_hdr_field_get_u32(hdr, TCP_ACK_SEQ));
189 FIELD("hlen=%d", proto_hdr_field_get_u16(hdr, TCP_DOFF));
190 if (proto_hdr_field_get_u16(hdr, TCP_CWR))
191 FIELD("cwr");
192 if (proto_hdr_field_get_u16(hdr, TCP_ECE))
193 FIELD("ecn");
194 if (proto_hdr_field_get_u16(hdr, TCP_URG))
195 FIELD("urg");
196 if (proto_hdr_field_get_u16(hdr, TCP_ACK))
197 FIELD("ack");
198 if (proto_hdr_field_get_u16(hdr, TCP_PSH))
199 FIELD("psh");
200 if (proto_hdr_field_get_u16(hdr, TCP_RST))
201 FIELD("rst");
202 if (proto_hdr_field_get_u16(hdr, TCP_SYN))
203 FIELD("syn");
204 if (proto_hdr_field_get_u16(hdr, TCP_FIN))
205 FIELD("fin");
206 FIELD("win=%d", proto_hdr_field_get_u16(hdr, TCP_WINDOW));
207 FIELD("csum=0x%x", proto_hdr_field_get_u16(hdr, TCP_CSUM));
208 FIELD_END("urgptr=0x%x", proto_hdr_field_get_u16(hdr, TCP_URG_PTR));
210 HDR_END();
211 return 0;
214 static int proto_dump_hdr(struct dump_ctx *ctx, struct proto_hdr *hdr)
216 switch (hdr->ops->id) {
217 case PROTO_ETH:
218 return proto_dump_eth(ctx, hdr);
219 case PROTO_VLAN:
220 return proto_dump_vlan(ctx, hdr);
221 case PROTO_ARP:
222 return proto_dump_arp(ctx, hdr);
223 case PROTO_IP4:
224 return proto_dump_ip4(ctx, hdr);
225 case PROTO_IP6:
226 return proto_dump_ip6(ctx, hdr);
227 case PROTO_UDP:
228 return proto_dump_udp(ctx, hdr);
229 case PROTO_TCP:
230 return proto_dump_tcp(ctx, hdr);
231 default:
232 return -1;
236 int packet_dump_fd(struct packet *pkt, int fd)
238 struct proto_hdr *hdr;
239 enum proto_id pid;
240 struct dump_ctx _ctx;
241 struct dump_ctx *ctx = &_ctx;
242 size_t dump_len = 0;
243 uint32_t i;
245 _ctx.file = fdopen(fd, "w");
246 if (!_ctx.file)
247 return -1;
249 /* handle case if there is already proto headers */
250 if (pkt->headers_count == 0) {
251 hdr = proto_packet_apply(PROTO_ETH, pkt);
253 while ((pid = proto_hdr_get_next_proto(hdr)) != __PROTO_MAX) {
254 if (hdr->pkt_offset + hdr->len >= pkt->len)
255 break;
257 hdr = proto_packet_apply(pid, pkt);
261 PKT_START();
262 for (i = 0; i < pkt->headers_count; i++) {
263 hdr = pkt->headers[i];
265 if (proto_dump_hdr(ctx, hdr))
266 break;
268 dump_len += hdr->len;
271 /* print rest as a bytes */
272 if (dump_len < pkt->len) {
273 int j = 1;
275 DUMP(" ");
276 for (i = dump_len; i < pkt->len; ++i, ++j) {
277 if (j % 15 == 0)
278 DUMP("\n ");
279 DUMP("0x%02x,", pkt->payload[i]);
281 DUMP("\n");
283 PKT_END();
285 fflush(ctx->file);
286 return 0;