source: lib/protocols_ospf.c @ 2193905

develop
Last change on this file since 2193905 was 2193905, checked in by Jacob Van Walraven <jcv9@…>, 2 years ago

Apply changes required for pull request #81

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