diff options
Diffstat (limited to 'babeld')
| -rw-r--r-- | babeld/message.c | 91 | ||||
| -rw-r--r-- | babeld/message.h | 1 | ||||
| -rw-r--r-- | babeld/util.h | 6 | 
3 files changed, 96 insertions, 2 deletions
diff --git a/babeld/message.c b/babeld/message.c index 15d772eb46..d4ddebff08 100644 --- a/babeld/message.c +++ b/babeld/message.c @@ -48,6 +48,13 @@ static const unsigned char tlv_min_length[MESSAGE_MAX + 1] =      [ MESSAGE_MH_REQUEST ] = 14,  }; +/* Checks whether an AE exists or must be silently ignored */ +static bool +known_ae(int ae) +{ +    return ae <= 4; +} +  /* Parse a network prefix, encoded in the somewhat baroque compressed     representation used by Babel.  Return the number of bytes parsed. */  static int @@ -277,6 +284,62 @@ parse_ihu_subtlv(const unsigned char *a, int alen,  }  static int +parse_request_subtlv(int ae, const unsigned char *a, int alen, +                     unsigned char *src_prefix, unsigned char *src_plen) +{ +    int type, len, i = 0; +    int have_src_prefix = 0; + +    while(i < alen) { +        type = a[0]; +        if(type == SUBTLV_PAD1) { +            i++; +            continue; +        } + +        if(i + 2 > alen) +            goto fail; + +        len = a[i + 1]; +        if(i + 2 + len > alen) +            goto fail; + +        if(type == SUBTLV_PADN) { +            /* Nothing to do. */ +        } else if(type == SUBTLV_SOURCE_PREFIX) { +            int rc; +            if(len < 1) +                goto fail; +            if(a[i + 2] == 0) +                goto fail; +            if(have_src_prefix != 0) +                goto fail; +            rc = network_prefix(ae, a[i + 2], 0, a + i + 3, NULL, +                                len - 1, src_prefix); +            if(rc < 0) +                goto fail; +            if(ae==1) +                *src_plen = a[i + 2] + 96; +            else +                *src_plen = a[i + 2]; +            have_src_prefix = 1; +        } else { +            debugf(BABEL_DEBUG_COMMON,"Received unknown%s Route Request sub-TLV %d.", +                   ((type & 0x80) != 0) ? " mandatory" : "", type); +            if((type & 0x80) != 0) +                return -1; +        } + +        i += len + 2; +    } +    return 1; + + fail: +    flog_err(EC_BABEL_PACKET, "Received truncated sub-TLV on Route Request."); +    return -1; +} + +static int  network_address(int ae, const unsigned char *a, unsigned int len,                  unsigned char *a_r)  { @@ -612,8 +675,14 @@ parse_packet(const unsigned char *from, struct interface *ifp,  				 interval, neigh, nh, channels,  				 channels_len(channels));  	} else if(type == MESSAGE_REQUEST) { -            unsigned char prefix[16], plen; -            int rc; +            unsigned char prefix[16], src_prefix[16], plen, src_plen; +            int rc, is_ss; +            if(len < 2) goto fail; +            if(!known_ae(message[2])) { +                debugf(BABEL_DEBUG_COMMON,"Received request with unknown AE %d. Ignoring.", +                       message[2]); +                goto done; +            }              rc = network_prefix(message[2], message[3], 0,                                  message + 4, NULL, len - 2, prefix);              if(rc < 0) goto fail; @@ -621,8 +690,26 @@ parse_packet(const unsigned char *from, struct interface *ifp,              debugf(BABEL_DEBUG_COMMON,"Received request for %s from %s on %s.",                     message[2] == 0 ? "any" : format_prefix(prefix, plen),                     format_address(from), ifp->name); +            if(message[2] == 1) { +                v4tov6(src_prefix, zeroes); +                src_plen = 96; +            } else { +                memcpy(src_prefix, zeroes, 16); +                src_plen = 0; +            } +            rc = parse_request_subtlv(message[2], message + 4 + rc, +                                      len - 2 - rc, src_prefix, &src_plen); +            if(rc < 0) +                goto done; +            is_ss = !is_default(src_prefix, src_plen);              if(message[2] == 0) {                  struct babel_interface *neigh_ifp =babel_get_if_nfo(neigh->ifp); +                if(is_ss) { +                    /* Wildcard requests don't carry a source prefix. */ +                    flog_err(EC_BABEL_PACKET, +			      "Received source-specific wildcard request."); +                    goto done; +                }                  /* If a neighbour is requesting a full route dump from us,                     we might as well send it an IHU. */                  send_ihu(neigh, NULL); diff --git a/babeld/message.h b/babeld/message.h index 0797a5a77d..7cf062a888 100644 --- a/babeld/message.h +++ b/babeld/message.h @@ -34,6 +34,7 @@ Copyright (c) 2007, 2008 by Juliusz Chroboczek  #define SUBTLV_PADN 1  #define SUBTLV_DIVERSITY 2 /* Also known as babelz. */  #define SUBTLV_TIMESTAMP 3 /* Used to compute RTT. */ +#define SUBTLV_SOURCE_PREFIX 128 /* Source-specific routing. */  #define SUBTLV_MANDATORY 0x80  extern unsigned short myseqno; diff --git a/babeld/util.h b/babeld/util.h index 8535d4dd6a..ddc6a70d43 100644 --- a/babeld/util.h +++ b/babeld/util.h @@ -104,6 +104,12 @@ void uchar_to_in6addr(struct in6_addr *dest, const unsigned char *src);  int daemonise(void);  extern const unsigned char v4prefix[16]; +static inline bool +is_default(const unsigned char *prefix, int plen) +{ +    return plen == 0 || (plen == 96 && v4mapped(prefix)); +} +  /* If debugging is disabled, we want to avoid calling format_address     for every omitted debugging message.  So debug is a macro.  But     vararg macros are not portable. */  | 
