1 /*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007-2012 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Authors: Daniel Lawson
8 * Perry Lorier
9 * Shane Alcock
10 *
11 * All rights reserved.
12 *
13 * This code has been developed by the University of Waikato WAND
14 * research group. For further information please see http://www.wand.net.nz/
15 *
16 * libtrace is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * libtrace is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with libtrace; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 * $Id: protocols_ospf.c 1745 2012-01-10 01:23:53Z salcock $
31 *
32 */
33
34 #include "libtrace.h"
35 #include "protocols.h"
36 #include <assert.h>
37 #include <stdlib.h>
38 #include <stdio.h> // fprintf
39
trace_get_ospf_header(libtrace_packet_t * packet,uint8_t * version,uint32_t * remaining)40 DLLEXPORT void *trace_get_ospf_header(libtrace_packet_t *packet,
41 uint8_t *version, uint32_t *remaining) {
42 uint8_t proto;
43 void *ospf;
44 uint32_t dummy_rem = 0;
45
46
47 if (!remaining)
48 remaining = &dummy_rem;
49
50 assert(version != NULL && "version may not be NULL when calling trace_get_ospf_header!");
51
52 ospf = trace_get_transport(packet, &proto, remaining);
53
54 if (!ospf || proto != TRACE_IPPROTO_OSPF || *remaining == 0)
55 return NULL;
56
57 *version = *((uint8_t *)ospf);
58
59 if (*version == 2 && *remaining < sizeof(libtrace_ospf_v2_t))
60 return NULL;
61
62 return ospf;
63 }
64
trace_get_ospf_contents_v2(libtrace_ospf_v2_t * header,uint8_t * ospf_type,uint32_t * remaining)65 DLLEXPORT void *trace_get_ospf_contents_v2(libtrace_ospf_v2_t *header,
66 uint8_t *ospf_type, uint32_t *remaining) {
67
68 uint8_t dummy_type;
69 char *ptr;
70
71 assert(remaining != NULL && "remaining may not be NULL when calling trace_get_ospf_contents!");
72
73 if (!ospf_type)
74 ospf_type = &dummy_type;
75
76 if (!header || *remaining < sizeof(libtrace_ospf_v2_t)) {
77 *ospf_type = 0;
78 *remaining = 0;
79 return NULL;
80 }
81
82 *ospf_type = header->type;
83
84 ptr = ((char *)header) + sizeof(libtrace_ospf_v2_t);
85 *remaining -= sizeof(libtrace_ospf_v2_t);
86
87 return (void *)ptr;
88
89 }
90
trace_get_first_ospf_link_from_router_lsa_v2(libtrace_ospf_router_lsa_v2_t * lsa,uint32_t * remaining)91 DLLEXPORT unsigned char *trace_get_first_ospf_link_from_router_lsa_v2(
92 libtrace_ospf_router_lsa_v2_t *lsa,
93 uint32_t *remaining) {
94
95 unsigned char *link_ptr = NULL;
96 assert(remaining != NULL && "remaining may not be NULL when calling trace_get_first_link_from_router_lsa_v2!");
97
98 if (!lsa || *remaining < sizeof(libtrace_ospf_router_lsa_v2_t)) {
99 *remaining = 0;
100 return NULL;
101 }
102
103 link_ptr = ((unsigned char *)lsa) + sizeof(libtrace_ospf_router_lsa_v2_t);
104 *remaining -= sizeof(libtrace_ospf_router_lsa_v2_t);
105 return link_ptr;
106
107 }
108
trace_get_first_ospf_lsa_from_db_desc_v2(libtrace_ospf_db_desc_v2_t * db_desc,uint32_t * remaining)109 DLLEXPORT unsigned char *trace_get_first_ospf_lsa_from_db_desc_v2(
110 libtrace_ospf_db_desc_v2_t *db_desc,
111 uint32_t *remaining) {
112
113 unsigned char *lsa_ptr = NULL;
114
115 assert(remaining != NULL && "remaining may not be NULL when calling trace_get_first_ospf_v2_lsa!");
116
117 if (!db_desc || *remaining < sizeof(libtrace_ospf_db_desc_v2_t)) {
118 *remaining = 0;
119 return NULL;
120 }
121
122 lsa_ptr = ((unsigned char *)db_desc) + sizeof(libtrace_ospf_db_desc_v2_t);
123 *remaining -= sizeof(libtrace_ospf_db_desc_v2_t);
124
125 return lsa_ptr;
126 }
127
trace_get_first_ospf_lsa_from_update_v2(libtrace_ospf_ls_update_t * ls_update,uint32_t * remaining)128 DLLEXPORT unsigned char *trace_get_first_ospf_lsa_from_update_v2(
129 libtrace_ospf_ls_update_t *ls_update,
130 uint32_t *remaining) {
131
132 unsigned char *lsa_ptr = NULL;
133
134 assert(remaining != NULL && "remaining may not be NULL when calling trace_get_first_ospf_v2_lsa!");
135
136 if (!ls_update || *remaining < sizeof(libtrace_ospf_ls_update_t)) {
137 *remaining = 0;
138 return NULL;
139 }
140
141 lsa_ptr = ((unsigned char *)ls_update) + sizeof(libtrace_ospf_ls_update_t);
142 *remaining -= sizeof(libtrace_ospf_ls_update_t);
143
144 return lsa_ptr;
145 }
146
trace_get_ospf_metric_from_as_external_lsa_v2(libtrace_ospf_as_external_lsa_v2_t * as_lsa)147 DLLEXPORT uint32_t trace_get_ospf_metric_from_as_external_lsa_v2(
148 libtrace_ospf_as_external_lsa_v2_t *as_lsa) {
149
150 uint32_t metric = 0;
151
152 assert(as_lsa);
153
154 metric = as_lsa->metric_a << 16;
155 metric |= (as_lsa->metric_b << 8);
156 metric |= as_lsa->metric_c;
157
158 return metric;
159 }
160
trace_get_ospf_metric_from_summary_lsa_v2(libtrace_ospf_summary_lsa_v2_t * sum_lsa)161 DLLEXPORT uint32_t trace_get_ospf_metric_from_summary_lsa_v2(
162 libtrace_ospf_summary_lsa_v2_t *sum_lsa) {
163
164 uint32_t metric = 0;
165
166 assert(sum_lsa);
167
168 metric = sum_lsa->metric_a << 16;
169 metric |= (sum_lsa->metric_b << 8);
170 metric |= sum_lsa->metric_c;
171
172 return metric;
173 }
174
trace_get_next_ospf_link_v2(unsigned char ** current,libtrace_ospf_link_v2_t ** link,uint32_t * remaining,uint32_t * link_len)175 DLLEXPORT int trace_get_next_ospf_link_v2(unsigned char **current,
176 libtrace_ospf_link_v2_t **link,
177 uint32_t *remaining,
178 uint32_t *link_len) {
179
180 if (*current == NULL || *remaining < sizeof(libtrace_ospf_link_v2_t)) {
181 *remaining = 0;
182 *link = NULL;
183 return 0;
184 }
185
186 *link = (libtrace_ospf_link_v2_t *)*current;
187
188 /* XXX The spec allows for multiple metrics for a single link. This
189 * approach won't support this, so we may need to be more intelligent
190 * about this in future */
191 *remaining -= sizeof(libtrace_ospf_link_v2_t);
192 *link_len = sizeof(libtrace_ospf_link_v2_t);
193 *current += sizeof(libtrace_ospf_link_v2_t);
194
195 return 1;
196
197 }
198
trace_get_next_ospf_lsa_header_v2(unsigned char ** current,libtrace_ospf_lsa_v2_t ** lsa_hdr,uint32_t * remaining,uint8_t * lsa_type,uint16_t * lsa_length)199 DLLEXPORT int trace_get_next_ospf_lsa_header_v2(unsigned char **current,
200 libtrace_ospf_lsa_v2_t **lsa_hdr,
201 uint32_t *remaining,
202 uint8_t *lsa_type,
203 uint16_t *lsa_length) {
204
205 int valid_lsa = 0;
206
207 if (*current == NULL || *remaining < sizeof(libtrace_ospf_lsa_v2_t)) {
208 *lsa_hdr = NULL;
209 *remaining = 0;
210 return 0;
211
212 }
213
214 *lsa_hdr = (libtrace_ospf_lsa_v2_t *)(*current);
215
216 /* Check that the LSA type is valid */
217 switch ((*lsa_hdr)->lsa_type) {
218 case TRACE_OSPF_LS_ROUTER:
219 case TRACE_OSPF_LS_NETWORK:
220 case TRACE_OSPF_LS_SUMMARY:
221 case TRACE_OSPF_LS_ASBR_SUMMARY:
222 case TRACE_OSPF_LS_EXTERNAL:
223 valid_lsa = 1;
224 break;
225 }
226
227 /* This function is for reading LSA headers only, e.g. those in DB desc
228 * or LS Ack packets. As such, I'm going to set the type and length to
229 * values that should prevent anyone from trying to treat subsequent
230 * payload as an LSA body */
231 *lsa_type = 0;
232 *lsa_length = sizeof(libtrace_ospf_lsa_v2_t);
233
234 if (!valid_lsa) {
235 *remaining = 0;
236 return -1;
237 }
238
239 *remaining -= *lsa_length;
240 *current += *lsa_length;
241
242 if (remaining == 0) {
243 /* No more LSAs */
244 return 0;
245 }
246 return 1;
247 }
248
trace_get_next_ospf_lsa_v2(unsigned char ** current,libtrace_ospf_lsa_v2_t ** lsa_hdr,unsigned char ** lsa_body,uint32_t * remaining,uint8_t * lsa_type,uint16_t * lsa_length)249 DLLEXPORT int trace_get_next_ospf_lsa_v2(unsigned char **current,
250 libtrace_ospf_lsa_v2_t **lsa_hdr,
251 unsigned char **lsa_body,
252 uint32_t *remaining,
253 uint8_t *lsa_type,
254 uint16_t *lsa_length) {
255
256 int valid_lsa = 0;
257
258 if (*current == NULL || *remaining < sizeof(libtrace_ospf_lsa_v2_t)) {
259 *lsa_hdr = NULL;
260 *lsa_body = NULL;
261 *remaining = 0;
262
263 return 0;
264
265 }
266
267 *lsa_hdr = (libtrace_ospf_lsa_v2_t *)(*current);
268 *lsa_type = (*lsa_hdr)->lsa_type;
269 *lsa_length = ntohs((*lsa_hdr)->length);
270
271 /* Check that the LSA type is valid */
272 switch (*lsa_type) {
273 case TRACE_OSPF_LS_ROUTER:
274 case TRACE_OSPF_LS_NETWORK:
275 case TRACE_OSPF_LS_SUMMARY:
276 case TRACE_OSPF_LS_ASBR_SUMMARY:
277 case TRACE_OSPF_LS_EXTERNAL:
278 valid_lsa = 1;
279 break;
280 }
281
282 if (*lsa_length > *remaining || !valid_lsa) {
283 /* LSA is incomplete or an invalid type.
284 *
285 * If this occurs, you've probably managed to read something
286 * that is NOT a legit LSA */
287 *remaining = 0;
288 *lsa_body = NULL;
289 return -1;
290 }
291
292 /* Some OSPF packets, e.g. LS ACKs, only contain LSA headers. If this
293 * is the case, we'll set the body pointer to NULL so the caller
294 * can't read invalid data */
295 if (*lsa_length == sizeof(libtrace_ospf_lsa_v2_t))
296 *lsa_body = NULL;
297 else
298 *lsa_body = (*current + sizeof(libtrace_ospf_lsa_v2_t));
299
300 *remaining -= *lsa_length;
301 *current += *lsa_length;
302
303 if (remaining == 0) {
304 /* No more LSAs */
305 return 0;
306 }
307
308 return 1;
309
310 }
311
312
313