Ignore:
Timestamp:
01/05/12 16:49:23 (9 years ago)
Author:
Shane Alcock <salcock@…>
Branches:
4.0.1-hotfixes, cachetimestamps, develop, dpdk-ndag, etsilive, getfragoff, help, libtrace4, master, ndag_format, pfring, rc-4.0.1, rc-4.0.2, rc-4.0.3, rc-4.0.4, ringdecrementfix, ringperformance, ringtimestampfixes
Children:
cc6fcee
Parents:
48d72f8
Message:

Added support for parsing OSPFv2 headers, based on Simon Wadsworth's 591 project.

A few comments on the implementation thus far:

  • This code has only been tested with Hello, LS Update and LS Acknowledge packets. DB Desc and LS Request is completely untested, mainly due to a lack of traces containing those packets.
  • This release supports not only accessing the basic OSPF headers but also parsing the interesting LSAs and Link Ids in LSA Update packets.
  • OSPF is not a nice protocol - there's lots of dynamic length stuff for starters. I've tried to design the API so that is as nice as possible for the end user who may not be overly knowledgeable about OSPF. In particular, I've tried to minimise the amount of pointer arithmetic needed to get at the LSAs and Link Ids. More documentation and an example program will come in a later commit.
  • Also, whoever came up with 24-bit metric values should be shot. To make life easier for users, I've included functions to return the correct value for the metric from a given header. I hope you all appreciate the extra effort :)
File:
1 edited

Legend:

Unmodified
Added
Removed
  • lib/protocols_transport.c

    ree58d0d r29532e3  
    194194}
    195195
     196DLLEXPORT void *trace_get_ospf_header(libtrace_packet_t *packet,
     197                uint8_t *version, uint32_t *remaining) {
     198        uint8_t proto;
     199        void *ospf;
     200        uint32_t dummy_rem = 0;
     201
     202
     203        if (!remaining)
     204                remaining = &dummy_rem;
     205
     206        assert(version != NULL && "version may not be NULL when calling trace_get_ospf_header!");
     207
     208        ospf = trace_get_transport(packet, &proto, remaining);
     209
     210        if (!ospf || proto != TRACE_IPPROTO_OSPF || *remaining == 0)
     211                return NULL;
     212
     213        *version = *((uint8_t *)ospf);
     214       
     215        if (*version == 2 && *remaining < sizeof(libtrace_ospf_v2_t))
     216                return NULL;
     217
     218        return ospf;
     219}
     220
     221DLLEXPORT void *trace_get_ospf_contents_v2(libtrace_ospf_v2_t *header,
     222                uint8_t *ospf_type, uint32_t *remaining) {
     223
     224        uint8_t dummy_type;
     225        char *ptr;
     226       
     227        assert(remaining != NULL && "remaining may not be NULL when calling trace_get_ospf_contents!");
     228
     229        if (!ospf_type)
     230                ospf_type = &dummy_type;
     231
     232        if (!header || *remaining < sizeof(libtrace_ospf_v2_t)) {
     233                *ospf_type = 0;
     234                *remaining = 0;
     235                return NULL;
     236        }
     237       
     238        *ospf_type = header->type;
     239
     240        ptr = ((char *)header) + sizeof(libtrace_ospf_v2_t);
     241        *remaining -= sizeof(libtrace_ospf_v2_t);
     242
     243        return (void *)ptr;
     244
     245}
     246
     247DLLEXPORT unsigned char *trace_get_first_ospf_link_from_router_lsa_v2(
     248                libtrace_ospf_router_lsa_v2_t *lsa,
     249                uint32_t *remaining) {
     250
     251        unsigned char *link_ptr = NULL;
     252        assert(remaining != NULL && "remaining may not be NULL when calling trace_get_first_link_from_router_lsa_v2!");
     253
     254        if (!lsa || *remaining < sizeof(libtrace_ospf_router_lsa_v2_t)) {
     255                *remaining = 0;
     256                return NULL;
     257        }
     258
     259        link_ptr = ((unsigned char *)lsa) + sizeof(libtrace_ospf_router_lsa_v2_t);
     260        *remaining -= sizeof(libtrace_ospf_router_lsa_v2_t);
     261        return link_ptr;
     262
     263}
     264
     265DLLEXPORT unsigned char *trace_get_first_ospf_lsa_from_db_desc_v2(
     266                libtrace_ospf_db_desc_v2_t *db_desc,
     267                uint32_t *remaining) {
     268
     269        unsigned char *lsa_ptr = NULL;
     270
     271        assert(remaining != NULL && "remaining may not be NULL when calling trace_get_first_ospf_v2_lsa!");
     272
     273        if (!db_desc || *remaining < sizeof(libtrace_ospf_db_desc_v2_t)) {
     274                *remaining = 0;
     275                return NULL;
     276        }
     277       
     278        lsa_ptr = ((unsigned char *)db_desc) + sizeof(libtrace_ospf_db_desc_v2_t);
     279        *remaining -= sizeof(libtrace_ospf_db_desc_v2_t);
     280
     281        return lsa_ptr;
     282}
     283
     284DLLEXPORT unsigned char *trace_get_first_ospf_lsa_from_update_v2(
     285                libtrace_ospf_ls_update_t *ls_update,
     286                uint32_t *remaining) {
     287
     288        unsigned char *lsa_ptr = NULL;
     289
     290        assert(remaining != NULL && "remaining may not be NULL when calling trace_get_first_ospf_v2_lsa!");
     291
     292        if (!ls_update || *remaining < sizeof(libtrace_ospf_ls_update_t)) {
     293                *remaining = 0;
     294                return NULL;
     295        }
     296       
     297        lsa_ptr = ((unsigned char *)ls_update) + sizeof(libtrace_ospf_ls_update_t);
     298        *remaining -= sizeof(libtrace_ospf_ls_update_t);
     299
     300        return lsa_ptr;
     301}
     302
     303DLLEXPORT uint32_t trace_get_ospf_metric_from_as_external_lsa_v2(
     304                libtrace_ospf_as_external_lsa_v2_t *as_lsa) {
     305
     306        uint32_t metric = 0;
     307
     308        assert(as_lsa);
     309
     310        metric = as_lsa->metric_a << 16;
     311        metric |= (as_lsa->metric_b << 8);
     312        metric |= as_lsa->metric_c;
     313
     314        return metric;
     315}
     316
     317DLLEXPORT uint32_t trace_get_ospf_metric_from_summary_lsa_v2(
     318                libtrace_ospf_summary_lsa_v2_t *sum_lsa) {
     319
     320        uint32_t metric = 0;
     321
     322        assert(sum_lsa);
     323
     324        metric = sum_lsa->metric_a << 16;
     325        metric |= (sum_lsa->metric_b << 8);
     326        metric |= sum_lsa->metric_c;
     327
     328        return metric;
     329}
     330
     331DLLEXPORT int trace_get_next_ospf_link_v2(unsigned char **current,
     332                libtrace_ospf_link_v2_t **link,
     333                uint32_t *remaining,
     334                uint32_t *link_len) {
     335
     336        if (*current == NULL || *remaining < sizeof(libtrace_ospf_link_v2_t)) {
     337                *remaining = 0;
     338                *link = NULL;
     339                return 0;
     340        }
     341
     342        *link = (libtrace_ospf_link_v2_t *)*current;
     343
     344        /* XXX The spec allows for multiple metrics for a single link. This
     345         * approach won't support this, so we may need to be more intelligent
     346         * about this in future */
     347        *remaining -= sizeof(libtrace_ospf_link_v2_t);
     348        *link_len = sizeof(libtrace_ospf_link_v2_t);
     349        *current += sizeof(libtrace_ospf_link_v2_t);
     350       
     351        return 1;
     352
     353}
     354
     355DLLEXPORT int trace_get_next_ospf_lsa_v2(unsigned char **current,
     356                libtrace_ospf_lsa_v2_t **lsa_hdr,
     357                unsigned char **lsa_body,
     358                uint32_t *remaining,
     359                uint8_t *lsa_type,
     360                uint16_t *lsa_length) {
     361
     362        int valid_lsa = 0;
     363
     364        if (*current == NULL || *remaining < sizeof(libtrace_ospf_lsa_v2_t)) {
     365                *lsa_hdr = NULL;
     366                *lsa_body = NULL;
     367                *remaining = 0;
     368
     369                return 0;
     370
     371        }
     372
     373        *lsa_hdr = (libtrace_ospf_lsa_v2_t *)(*current);
     374        *lsa_type = (*lsa_hdr)->lsa_type;
     375        *lsa_length = ntohs((*lsa_hdr)->length);
     376
     377        /* Check that the LSA type is valid */
     378        switch (*lsa_type) {
     379                case TRACE_OSPF_LS_ROUTER:
     380                case TRACE_OSPF_LS_NETWORK:
     381                case TRACE_OSPF_LS_SUMMARY:
     382                case TRACE_OSPF_LS_ASBR_SUMMARY:
     383                case TRACE_OSPF_LS_EXTERNAL:
     384                        valid_lsa = 1;
     385                        break;
     386        }
     387               
     388        if (*lsa_length > *remaining || !valid_lsa) {
     389                /* LSA is incomplete or an invalid type.
     390                 *
     391                 * If this occurs, you've probably managed to read something
     392                 * that is NOT a legit LSA */
     393                *remaining = 0;
     394                return -1;
     395        }
     396       
     397        /* Some OSPF packets, e.g. LS ACKs, only contain LSA headers. If this
     398         * is the case, we'll set the body pointer to NULL so the caller
     399         * can't read invalid data */
     400        if (*lsa_length == sizeof(libtrace_ospf_lsa_v2_t))
     401                *lsa_body = NULL;
     402        else
     403                *lsa_body = (*current + sizeof(libtrace_ospf_lsa_v2_t));
     404
     405        *remaining -= *lsa_length;
     406        *current += *lsa_length;
     407
     408        if (remaining == 0) {
     409                /* No more LSAs */
     410                return 0;
     411        }
     412
     413        return 1;
     414
     415}
     416
    196417DLLEXPORT libtrace_tcp_t *trace_get_tcp(libtrace_packet_t *packet) {
    197418        uint8_t proto;
Note: See TracChangeset for help on using the changeset viewer.