Changeset 29532e3


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 :)
Location:
lib
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • lib/libtrace.h.in

    r979a84f4 r29532e3  
    391391        TRACE_IPPROTO_NONE      = 59,   /**< IPv6 no next header */
    392392        TRACE_IPPROTO_DSTOPTS   = 60,   /**< IPv6 destination options */
     393        TRACE_IPPROTO_OSPF      = 89,   /**< Open Shortest Path First routing protocol */
    393394        TRACE_IPPROTO_PIM       = 103,  /**< Protocol Independant Multicast */
    394395        TRACE_IPPROTO_SCTP      = 132   /**< Stream Control Transmission Protocol */
     
    761762} PACKED libtrace_radiotap_t;
    762763
     764/** OSPF header */
     765typedef struct libtrace_ospf_v2_t
     766{
     767        uint8_t ospf_v;
     768        uint8_t type;
     769        uint16_t len;
     770        struct in_addr router;
     771        struct in_addr area;
     772        uint16_t sum;
     773        uint16_t au_type;
     774        uint16_t zero;
     775        uint8_t au_key_id;
     776        uint8_t au_data_len;
     777        uint32_t au_seq_num;
     778} PACKED libtrace_ospf_v2_t;
     779
     780typedef struct libtrace_ospf_options_t {
     781#if BYTE_ORDER == LITTLE_ENDIAN
     782        LT_BITFIELD8 unused1:1;
     783        LT_BITFIELD8 e_bit:1;
     784        LT_BITFIELD8 mc_bit:1;
     785        LT_BITFIELD8 np_bit:1;
     786        LT_BITFIELD8 ea_bit:1;
     787        LT_BITFIELD8 dc_bit:1;
     788        LT_BITFIELD8 unused2:2;
     789#elif BYTE_ORDER == BIG_ENDIAN
     790        LT_BITFIELD8 unused2:2;
     791        LT_BITFIELD8 dc_bit:1;
     792        LT_BITFIELD8 ea_bit:1;
     793        LT_BITFIELD8 np_bit:1;
     794        LT_BITFIELD8 mc_bit:1;
     795        LT_BITFIELD8 e_bit:1;
     796        LT_BITFIELD8 unused1:1;
     797#endif
     798} PACKED libtrace_ospf_options_t;
     799
     800typedef struct libtrace_ospf_lsa_v2_t
     801{
     802        uint16_t age;
     803        libtrace_ospf_options_t lsa_options;
     804        uint8_t lsa_type;
     805        struct in_addr ls_id;
     806        struct in_addr adv_router;
     807        uint32_t seq;
     808        uint16_t checksum;
     809        uint16_t length;
     810} PACKED libtrace_ospf_lsa_v2_t;
     811
     812typedef struct libtrace_ospf_hello_v2_t
     813{
     814        struct in_addr mask;
     815        uint16_t interval;
     816        libtrace_ospf_options_t hello_options;
     817        uint8_t priority;
     818        uint32_t deadint;
     819        struct in_addr designated;
     820        struct in_addr backup;
     821        struct in_addr neighbor;
     822} PACKED libtrace_ospf_hello_v2_t;
     823
     824typedef struct libtrace_ospf_db_desc_v2_t
     825{
     826        uint16_t mtu;
     827        uint8_t db_desc_options;
     828#if BYTE_ORDER == LITTLE_ENDIAN
     829        LT_BITFIELD8 db_desc_ms:1;
     830        LT_BITFIELD8 db_desc_m:1;
     831        LT_BITFIELD8 db_desc_i:1;
     832        LT_BITFIELD8 zero:5;
     833#elif BYTE_ORDER == BIG_ENDIAN
     834        LT_BITFIELD8 zero:5;
     835        LT_BITFIELD8 db_desc_i:1;
     836        LT_BITFIELD8 db_desc_m:1;
     837        LT_BITFIELD8 db_desc_ms:1;
     838#endif
     839        uint32_t seq;
     840} PACKED libtrace_ospf_db_desc_v2_t;
     841
     842typedef struct libtrace_ospf_ls_req_t
     843{
     844        uint32_t ls_type;
     845        uint32_t ls_id;
     846        uint32_t advertising_router;
     847} PACKED libtrace_ospf_ls_req_t;
     848
     849typedef struct libtrace_ospf_ls_update_t
     850{
     851        uint32_t ls_num_adv;
     852} PACKED libtrace_ospf_ls_update_t;
     853
     854typedef struct libtrace_ospf_as_external_lsa_t
     855{
     856        struct in_addr netmask;
     857#if BYTE_ORDER == LITTLE_ENDIAN
     858        LT_BITFIELD8 tos:7;
     859        LT_BITFIELD8 e:1;
     860#elif BYTE_ORDER == BIG_ENDIAN
     861        LT_BITFIELD8 e:1;
     862        LT_BITFIELD8 tos:7;
     863#endif
     864        uint8_t metric_a;
     865        uint8_t metric_b;
     866        uint8_t metric_c;       
     867        struct in_addr forwarding;
     868        uint32_t external_tag;
     869} PACKED libtrace_ospf_as_external_lsa_v2_t;
     870
     871typedef struct libtrace_ospf_summary_lsa
     872{
     873        struct in_addr netmask;
     874        uint8_t zero;
     875        uint8_t metric_a;
     876        uint8_t metric_b;
     877        uint8_t metric_c;       
     878       
     879} PACKED libtrace_ospf_summary_lsa_v2_t;
     880
     881typedef struct libtrace_ospf_network_lsa_t
     882{
     883        struct in_addr netmask;
     884} PACKED libtrace_ospf_network_lsa_v2_t;
     885
     886typedef struct libtrace_ospf_link_t
     887{
     888        struct in_addr link_id;
     889        struct in_addr link_data;
     890        uint8_t type;
     891        uint8_t num_tos;
     892        uint16_t tos_metric;
     893} PACKED libtrace_ospf_link_v2_t;
     894
     895typedef struct libtrace_ospf_router_lsa_t
     896{
     897#if BYTE_ORDER == LITTLE_ENDIAN
     898        LT_BITFIELD8 b:1;
     899        LT_BITFIELD8 e:1;
     900        LT_BITFIELD8 v:1;
     901        LT_BITFIELD8 zero:5;
     902#elif BYTE_ORDER == BIG_ENDIAN
     903        LT_BITFIELD8 zero:5;
     904        LT_BITFIELD8 v:1;
     905        LT_BITFIELD8 e:1;
     906        LT_BITFIELD8 b:1;
     907#endif
     908        uint8_t zero2;
     909        uint16_t num_links;
     910} PACKED libtrace_ospf_router_lsa_v2_t;
     911
     912typedef enum {
     913        TRACE_OSPF_HELLO = 1,
     914        TRACE_OSPF_DATADESC = 2,
     915        TRACE_OSPF_LSREQ = 3,
     916        TRACE_OSPF_LSUPDATE = 4,
     917        TRACE_OSPF_LSACK = 5
     918} libtrace_ospf_types_t;
     919
     920typedef enum {
     921        TRACE_OSPF_LS_ROUTER = 1,
     922        TRACE_OSPF_LS_NETWORK = 2,
     923        TRACE_OSPF_LS_SUMMARY = 3,
     924        TRACE_OSPF_LS_ASBR_SUMMARY = 4,
     925        TRACE_OSPF_LS_EXTERNAL = 5
     926} libtrace_ospf_ls_types_t;
     927
    763928
    764929#ifdef WIN32
     
    17971962DLLEXPORT SIMPLE_FUNCTION
    17981963libtrace_icmp_t *trace_get_icmp_from_ip(libtrace_ip_t *ip,uint32_t *remaining);
     1964
     1965/** Get a pointer to the OSPF header (if present)
     1966 * @param packet        The packet to get the OSPF header from
     1967 * @param[out] version  The OSPF version number
     1968 * @param[out] remaining        Updated with the number of captured bytes remaining
     1969 * @return A pointer to the start of the OSPF header or NULL if there is no
     1970 * complete OSPF header present in the packet
     1971 *
     1972 * This is a short-cut function enabling quick and easy access to the OSPF
     1973 * header. If you only care about the OSPF header, this function may be useful
     1974 * but we otherwise recommend the use of the more generic trace_get_transport()
     1975 * function instead.
     1976 *
     1977 * Upon return, 'version' is updated to contain the OSPF version number for the
     1978 * packet so that the returned pointer may be cast to the correct type.
     1979 * The version parameter MUST contain a valid pointer; it MUST NOT be NULL.
     1980 *
     1981 * 'remaining' is also set to contain the number of captured bytes remaining
     1982 * starting from the pointer returned by this function.
     1983 *
     1984 * @note Unlike trace_get_transport(), this function will return NULL if the
     1985 * OSPF header is incomplete or truncated.
     1986 */
     1987DLLEXPORT SIMPLE_FUNCTION
     1988void *trace_get_ospf_header(libtrace_packet_t *packet, uint8_t *version,
     1989                uint32_t *remaining);
     1990
     1991/** Get a pointer to the contents of the OSPF packet *after* the OSPF header
     1992 * @param header        The OSPF header to get the OSPF contents from
     1993 * @param[out] ospf_type        The OSPF packet type
     1994 * @param[in, out] remaining    Updated with the number of captured bytes remaining
     1995 * @return A pointer to the first byte after the OSPF header.
     1996 *
     1997 * This function returns a void pointer that can be cast appropriately
     1998 * based on the ospf_type. For example, if the ospf_type is TRACE_OSPF_HELLO
     1999 * then the return pointer should be cast as a libtrace_ospf_hello_v2_t
     2000 * structure.
     2001 *
     2002 * If the OSPF header is truncated, then NULL will be returned. If the OSPF
     2003 * contents are missing or truncated, the pointer to the start of the content
     2004 * will still be returned so be careful to check the value of remaining.
     2005 *
     2006 * 'remaining' MUST be set to the amount of bytes remaining in the captured
     2007 * packet starting from the beginning of the OSPF header. It will be updated
     2008 * to contain the number of bytes remaining from the start of the OSPF contents.
     2009 *
     2010 * @note This function only works for OSPF version 2 packets.
     2011 * @note Use trace_get_first_ospf_lsa() and trace_get_next_ospf_lsa() to read the LSAs from Link State Request
     2012 * and Update packets.
     2013 *
     2014 */
     2015DLLEXPORT SIMPLE_FUNCTION
     2016void *trace_get_ospf_contents_v2(libtrace_ospf_v2_t *header,
     2017                uint8_t *ospf_type, uint32_t *remaining);
     2018
     2019DLLEXPORT SIMPLE_FUNCTION
     2020unsigned char *trace_get_first_ospf_lsa_from_update_v2(
     2021                libtrace_ospf_ls_update_t *ls_update,
     2022                uint32_t *remaining);
     2023
     2024DLLEXPORT SIMPLE_FUNCTION
     2025unsigned char *trace_get_first_ospf_lsa_from_db_desc_v2(
     2026                libtrace_ospf_db_desc_v2_t *db_desc,
     2027                uint32_t *remaining);
     2028
     2029DLLEXPORT SIMPLE_FUNCTION
     2030unsigned char *trace_get_first_ospf_link_from_router_lsa_v2(
     2031                libtrace_ospf_router_lsa_v2_t *lsa,
     2032                uint32_t *remaining);
     2033
     2034DLLEXPORT SIMPLE_FUNCTION
     2035int trace_get_next_ospf_link_v2(unsigned char **current,
     2036                libtrace_ospf_link_v2_t **link,
     2037                uint32_t *remaining,
     2038                uint32_t *link_len);
     2039
     2040DLLEXPORT SIMPLE_FUNCTION
     2041int trace_get_next_ospf_lsa_v2(unsigned char **current,
     2042                libtrace_ospf_lsa_v2_t **lsa_hdr,
     2043                unsigned char **lsa_body,
     2044                uint32_t *remaining,
     2045                uint8_t *lsa_type,
     2046                uint16_t *lsa_length);
     2047
     2048DLLEXPORT SIMPLE_FUNCTION
     2049uint32_t trace_get_ospf_metric_from_as_external_lsa_v2(
     2050                libtrace_ospf_as_external_lsa_v2_t *as_lsa);
     2051
     2052DLLEXPORT SIMPLE_FUNCTION
     2053uint32_t trace_get_ospf_metric_from_summary_lsa_v2(
     2054                libtrace_ospf_summary_lsa_v2_t *sum_lsa);
     2055
    17992056
    18002057/** Gets the destination MAC address for a given packet
  • 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.