Implement lid_length mechanism into DLEP
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Wed, 11 Apr 2018 09:29:16 +0000 (11:29 +0200)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Wed, 11 Apr 2018 09:29:16 +0000 (11:29 +0200)
src-plugins/generic/dlep/dlep_extension.c
src-plugins/generic/dlep/dlep_iana.h
src-plugins/generic/dlep/dlep_reader.c
src-plugins/generic/dlep/dlep_reader.h
src-plugins/generic/dlep/dlep_session.c
src-plugins/generic/dlep/dlep_session.h
src-plugins/generic/dlep/dlep_writer.c
src-plugins/generic/dlep/dlep_writer.h
src-plugins/generic/dlep/ext_lid/lid.c
src-plugins/generic/dlep/radio/dlep_radio.c

index 20a877c..1e8c7d4 100644 (file)
@@ -207,8 +207,9 @@ dlep_extension_get_l2_neighbor_key(struct oonf_layer2_neigh_key *key, struct dle
   if (dlep_reader_lid_tlv(key, session, NULL)) {
     OONF_DEBUG(session->log_source, "lid tlv not present");
   }
-  else if (!session->allow_lids) {
-    OONF_INFO(session->log_source, "LID TLV is not allowed");
+  else if (key->link_id_length != session->cfg.lid_length) {
+    OONF_INFO(session->log_source, "LID TLV (length=%u) with bad length (should be %u)",
+              key->link_id_length, session->cfg.lid_length);
     return -1;
   }
   return 0;
index afa6915..871a6f5 100644 (file)
 
 /*! TCP port for DLEP radio server port */
 #define DLEP_WELL_KNOWN_SESSION_PORT_TXT "854"
+
+/*! Default Link-ID length in Octets for configuration */
+#define DLEP_DEFAULT_LID_LENGTH_TXT "4"
+
 /**
- * Generic DLEP Constant
+ * Generic DLEP Constants
  */
 enum
 {
   /*! DLEP IANA_PORT */
   DLEP_PORT = 854, //!< DLEP_PORT
+
+  /*! used for link id extension */
+  DLEP_DEFAULT_LID_LENGTH = 4,
 };
 
 /*! magic word for DLEP session */
@@ -245,6 +252,8 @@ enum dlep_tlvs
   /*! link ID TLV */
   DLEP_LID_TLV = 21,
 
+  /*! link ID TLV */
+  DLEP_LID_LENGTH_TLV = 22,
 
   /* l1 statistics */
 
index af3619c..3842ad4 100644 (file)
@@ -168,6 +168,32 @@ dlep_reader_lid_tlv(struct oonf_layer2_neigh_key *key, struct dlep_session *sess
 }
 
 /**
+ * Parse a DLEP link-id length TLV
+ * @param length pointer to link-id length storage
+ * @param session dlep session
+ * @param value dlep value to parse, NULL for using the first
+ *   DLEP_LID_TLV value
+ * @return -1 if an error happened, 0 otherwise
+ */
+int
+dlep_reader_lid_length_tlv(uint16_t *length, struct dlep_session *session, struct dlep_parser_value *value) {
+  const uint8_t *ptr;
+  uint16_t tmp16;
+  if (!value) {
+    value = dlep_session_get_tlv_value(session, DLEP_LID_TLV);
+    if (!value) {
+      return -1;
+    }
+  }
+
+  ptr = dlep_session_get_tlv_binary(session, value);
+  memcpy(&tmp16, ptr, sizeof(tmp16));
+  *length = ntohs(tmp16);
+
+  return 0;
+}
+
+/**
  * Parse DLEP IPv4 address TLV
  * @param ipv4 pointer to address storage
  * @param add pointer to boolean for flag storage
index 7b2f9ff..5e28e8a 100644 (file)
@@ -58,6 +58,7 @@ int dlep_reader_peer_type(
   char *text, size_t text_length, bool *secured, struct dlep_session *session, struct dlep_parser_value *value);
 int dlep_reader_mac_tlv(struct oonf_layer2_neigh_key *lid, struct dlep_session *session, struct dlep_parser_value *value);
 int dlep_reader_lid_tlv(struct oonf_layer2_neigh_key *lid, struct dlep_session *session, struct dlep_parser_value *value);
+int dlep_reader_lid_length_tlv(uint16_t *length, struct dlep_session *session, struct dlep_parser_value *value);
 int dlep_reader_ipv4_tlv(
   struct netaddr *ipv4, bool *add, struct dlep_session *session, struct dlep_parser_value *value);
 int dlep_reader_ipv6_tlv(
index 1b450c2..1d751bc 100644 (file)
@@ -458,7 +458,7 @@ dlep_session_add_local_neighbor(struct dlep_session *session, const struct oonf_
     return local;
   }
 
-  if (key->link_id_length > 0 && !session->allow_lids) {
+  if (key->link_id_length != 0 && key->link_id_length != session->cfg.lid_length) {
     /* LIDs not allowed */
     return NULL;
   }
index f9dfeb9..31263ad 100644 (file)
@@ -252,6 +252,9 @@ struct dlep_session_config {
 
   /*! true if proxied neighbors should be sent with DLEP */
   bool send_proxied;
+
+  /*! length of LIDs used to communicate with router */
+  uint16_t lid_length;
 };
 
 /**
@@ -283,9 +286,6 @@ struct dlep_session {
   /*! true if this is a radio session */
   bool radio;
 
-  /*! true if LID tagged neighbor information can be transmitted over the link */
-  bool allow_lids;
-
   /*! parser for this dlep session */
   struct dlep_session_parser parser;
 
index 3bd099d..aab5da3 100644 (file)
@@ -214,6 +214,21 @@ dlep_writer_add_lid_tlv(struct dlep_writer *writer, const struct oonf_layer2_nei
 }
 
 /**
+ * Write a DLEP Link-ID length TLV
+ * @param writer dlep writer
+ * @param link_id_length length of link-id
+ * @return -1 if address was wrong type, 0 otherwise
+ */
+int
+dlep_writer_add_lid_length_tlv(struct dlep_writer *writer, uint16_t link_id_length) {
+  uint16_t value;
+
+  value = htons(link_id_length);
+  dlep_writer_add_tlv(writer, DLEP_LID_LENGTH_TLV, &value, sizeof(value));
+  return 0;
+}
+
+/**
  * Write a DLEP IPv4/IPv6 address/subnet TLV
  * @param writer dlep writer
  * @param ip IPv4 address
index c0020dd..4eb9185 100644 (file)
@@ -63,6 +63,7 @@ void dlep_writer_add_heartbeat_tlv(struct dlep_writer *writer, uint64_t interval
 void dlep_writer_add_peer_type_tlv(struct dlep_writer *writer, const char *peer_type, bool access_control);
 int dlep_writer_add_mac_tlv(struct dlep_writer *writer, const struct oonf_layer2_neigh_key *mac_lid);
 int dlep_writer_add_lid_tlv(struct dlep_writer *writer, const struct oonf_layer2_neigh_key *mac_lid);
+int dlep_writer_add_lid_length_tlv(struct dlep_writer *writer, uint16_t link_id_length);
 int dlep_writer_add_ip_tlv(struct dlep_writer *writer, const struct netaddr *ipv4, bool add);
 void dlep_writer_add_ipv4_conpoint_tlv(struct dlep_writer *writer, const struct netaddr *addr, uint16_t port, bool tls);
 void dlep_writer_add_ipv6_conpoint_tlv(struct dlep_writer *writer, const struct netaddr *addr, uint16_t port, bool tls);
index b3e3c7b..3655842 100644 (file)
 
 #include "dlep/ext_lid/lid.h"
 
-static int _write_lid_only(struct dlep_extension *ext, struct dlep_session *session, const struct oonf_layer2_neigh_key *neigh);
-static void _cb_session_init(struct dlep_session *session);
 static void _cb_session_deactivate(struct dlep_session *session);
+static int _write_lid_only(struct dlep_extension *ext, struct dlep_session *session, const struct oonf_layer2_neigh_key *neigh);
+static int _write_session_init_ack(struct dlep_extension *ext, struct dlep_session *session, const struct oonf_layer2_neigh_key *neigh);
+static enum dlep_parser_error _process_session_init_ack(struct dlep_extension *ext, struct dlep_session *session);
 
-/* UDP peer discovery */
+/* session initialization ack */
+static const uint16_t _session_initack_tlvs[] = {
+  DLEP_LID_LENGTH_TLV,
+};
 
 /* destination up */
 static const uint16_t _dst_up_tlvs[] = {
@@ -120,6 +124,13 @@ static const uint16_t _linkchar_ack_mandatory[] = {
 /* supported signals of this extension, parsing the LID TLV is done by dlep_extension */
 static struct dlep_extension_signal _signals[] = {
   {
+    .id = DLEP_SESSION_INITIALIZATION_ACK,
+    .supported_tlvs = _session_initack_tlvs,
+    .supported_tlv_count = ARRAYSIZE(_session_initack_tlvs),
+    .process_radio = _process_session_init_ack,
+    .add_router_tlvs = _write_session_init_ack,
+  },
+  {
     .id = DLEP_DESTINATION_UP,
     .supported_tlvs = _dst_up_tlvs,
     .supported_tlv_count = ARRAYSIZE(_dst_up_tlvs),
@@ -192,8 +203,6 @@ static struct dlep_extension _lid = {
   .tlvs = _tlvs,
   .tlv_count = ARRAYSIZE(_tlvs),
 
-  .cb_session_init_radio = _cb_session_init,
-  .cb_session_init_router = _cb_session_init,
   .cb_session_deactivate_radio = _cb_session_deactivate,
   .cb_session_deactivate_router = _cb_session_deactivate,
 };
@@ -208,6 +217,11 @@ dlep_lid_init(void) {
   return &_lid;
 }
 
+static void
+_cb_session_deactivate(struct dlep_session *session) {
+  session->cfg.lid_length = 0;
+}
+
 /**
  * Write the link-id TLV into the DLEP message
  * @param ext (this) dlep extension
@@ -218,18 +232,31 @@ dlep_lid_init(void) {
 static int
 _write_lid_only(
   struct dlep_extension *ext __attribute__((unused)), struct dlep_session *session, const struct oonf_layer2_neigh_key *neigh) {
-  if (dlep_writer_add_lid_tlv(&session->writer, neigh)) {
-    return -1;
-  }
-  return 0;
+  return dlep_writer_add_lid_tlv(&session->writer, neigh);
 }
 
-static void
-_cb_session_init(struct dlep_session *session) {
-  session->allow_lids = true;
+static int
+_write_session_init_ack(struct dlep_extension *ext __attribute__((unused)), struct dlep_session *session,
+                        const struct oonf_layer2_neigh_key *neigh __attribute__((unused))) {
+  if (session->cfg.lid_length == 0 || session->cfg.lid_length == DLEP_DEFAULT_LID_LENGTH) {
+    return 0;
+  }
+
+  return dlep_writer_add_lid_length_tlv(&session->writer, session->cfg.lid_length);
 }
 
-static void
-_cb_session_deactivate(struct dlep_session *session) {
-  session->allow_lids = false;
+static enum dlep_parser_error
+_process_session_init_ack(struct dlep_extension *ext __attribute__((unused)), struct dlep_session *session) {
+  uint16_t length;
+
+  if (dlep_reader_lid_length_tlv(&length, session, NULL)) {
+    return DLEP_NEW_PARSER_OKAY;
+  }
+
+  if (length > OONF_LAYER2_MAX_LINK_ID) {
+    dlep_session_generate_signal_status(session, DLEP_SESSION_TERMINATION, NULL, DLEP_STATUS_REQUEST_DENIED,
+        "Cannot handle link-id length this large");
+    return DLEP_NEW_PARSER_TERMINDATED;
+  }
+  return DLEP_NEW_PARSER_OKAY;
 }
index 8cc9b8c..3c5cb42 100644 (file)
@@ -111,6 +111,9 @@ static struct cfg_schema_entry _radio_entries[] = {
   CFG_MAP_BOOL(dlep_radio_if, interf.session.cfg.send_proxied, "proxied", "true",
     "Report 802.11s proxied mac address for neighbors"),
   CFG_MAP_BOOL(dlep_radio_if, interf.session.cfg.send_neighbors, "not_proxied", "false", "Report direct neighbors"),
+
+  CFG_MAP_INT32_MINMAX(dlep_radio_if, interf.session.cfg.lid_length, "lid_length", DLEP_DEFAULT_LID_LENGTH_TXT,
+    "Link-ID length in octets that can be used to communicate with router", 0, 0, OONF_LAYER2_MAX_LINK_ID-1),
 };
 
 static struct cfg_schema_section _radio_section = {