man: improvements to language for astraceroute.8
[netsniff-ng.git] / proto_ipv6_routing.c
blob735f976edcd02350640a963c1ddd4578c5d2f3ee
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2012 Markus Amend <markus@netsniff-ng.org>, Deutsche Flugsicherung GmbH
4 * Subject to the GPL, version 2.
6 * IPv6 Routing Header described in RFC2460
7 */
9 #include <stdio.h>
10 #include <stdint.h>
11 #include <netinet/in.h> /* for ntohs() and "struct in6_addr" */
12 #include <arpa/inet.h> /* for inet_ntop() */
14 #include "proto.h"
15 #include "protos.h"
16 #include "dissector_eth.h"
17 #include "built_in.h"
18 #include "pkt_buff.h"
20 #define ROUTING_HEADER_TYPE_0 0x00
22 struct routinghdr {
23 uint8_t h_next_header;
24 uint8_t h_hdr_ext_len;
25 uint8_t h_routing_type;
26 uint8_t h_segments_left;
27 } __packed;
29 struct routinghdr_0 {
30 uint32_t reserved;
31 uint32_t addresses[0];
32 } __packed;
34 static void dissect_routinghdr_type_0(struct pkt_buff *pkt,
35 ssize_t *data_len, int less)
37 uint8_t num_addr;
38 char address[INET6_ADDRSTRLEN];
39 struct in6_addr *addr;
40 struct routinghdr_0 *routing_0;
42 routing_0 = (struct routinghdr_0 *) pkt_pull(pkt, sizeof(*routing_0));
43 *data_len -= sizeof(*routing_0);
44 if (routing_0 == NULL || *data_len > pkt_len(pkt) || *data_len < 0)
45 return;
47 if (less) {
48 tprintf("Addresses (%lu)", *data_len / sizeof(struct in6_addr));
49 return;
52 tprintf("Res (0x%x)", routing_0->reserved);
54 num_addr = *data_len / sizeof(*addr);
56 while (num_addr--) {
57 addr = (struct in6_addr *) pkt_pull(pkt, sizeof(*addr));
58 *data_len -= sizeof(*addr);
59 if (addr == NULL || *data_len > pkt_len(pkt) || *data_len < 0)
60 return;
62 tprintf("\n\t Address: %s",
63 inet_ntop(AF_INET6, addr, address,
64 sizeof(address)));
68 static inline void dissect_routinghdr_type_0_norm(struct pkt_buff *pkt,
69 ssize_t *data_len)
71 dissect_routinghdr_type_0(pkt, data_len, 0);
74 static inline void dissect_routinghdr_type_0_less(struct pkt_buff *pkt,
75 ssize_t *data_len)
77 dissect_routinghdr_type_0(pkt, data_len, 1);
80 static void routing(struct pkt_buff *pkt)
82 uint16_t hdr_ext_len;
83 ssize_t data_len;
84 struct routinghdr *routing;
86 routing = (struct routinghdr *) pkt_pull(pkt, sizeof(*routing));
87 if (routing == NULL)
88 return;
90 /* Total Header Length in Bytes */
91 hdr_ext_len = (routing->h_hdr_ext_len + 1) * 8;
92 /* Data length in Bytes */
93 data_len = hdr_ext_len - sizeof(*routing);
95 tprintf("\t [ Routing ");
96 tprintf("NextHdr (%u), ", routing->h_next_header);
97 if (data_len > pkt_len(pkt) || data_len < 0){
98 tprintf("HdrExtLen (%u, %u Bytes %s), ", routing->h_hdr_ext_len,
99 hdr_ext_len, colorize_start_full(black, red)
100 "invalid" colorize_end());
101 return;
103 tprintf("HdrExtLen (%u, %u Bytes), ", routing->h_hdr_ext_len,
104 hdr_ext_len);
105 tprintf("Type (%u), ", routing->h_routing_type);
106 tprintf("Left (%u), ", routing->h_segments_left);
108 switch (routing->h_routing_type) {
109 case ROUTING_HEADER_TYPE_0:
110 dissect_routinghdr_type_0_norm(pkt, &data_len);
111 break;
112 default:
113 tprintf("Type %u is unknown", routing->h_routing_type);
116 tprintf(" ]\n");
118 if (data_len > pkt_len(pkt) || data_len < 0)
119 return;
121 pkt_pull(pkt, data_len);
122 pkt_set_proto(pkt, &eth_lay3, routing->h_next_header);
125 static void routing_less(struct pkt_buff *pkt)
127 uint16_t hdr_ext_len;
128 ssize_t data_len;
129 struct routinghdr *routing;
131 routing = (struct routinghdr *) pkt_pull(pkt, sizeof(*routing));
132 if (routing == NULL)
133 return;
135 /* Total Header Length in Bytes */
136 hdr_ext_len = (routing->h_hdr_ext_len + 1) * 8;
137 /* Data length in Bytes */
138 data_len = hdr_ext_len - sizeof(*routing);
139 if (data_len > pkt_len(pkt) || data_len < 0)
140 return;
142 tprintf(" Routing ");
144 switch (routing->h_routing_type) {
145 case ROUTING_HEADER_TYPE_0:
146 dissect_routinghdr_type_0_less(pkt, &data_len);
147 break;
148 default:
149 tprintf("Type %u is unknown", routing->h_routing_type);
152 if (data_len > pkt_len(pkt) || data_len < 0)
153 return;
155 pkt_pull(pkt, data_len);
156 pkt_set_proto(pkt, &eth_lay3, routing->h_next_header);
159 struct protocol ipv6_routing_ops = {
160 .key = 0x2B,
161 .print_full = routing,
162 .print_less = routing_less,