summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiri Pirko <jiri@resnulli.us>2013-04-05 15:24:55 +0200
committerJiri Pirko <jiri@resnulli.us>2013-04-05 16:30:16 +0200
commit7186b5235eda2ab4b42770f0149d9324fd39d9d2 (patch)
treef04a22d627c0e53ce313f352a9a51e62e03d263d
parenteebfbcd0eca46345c51ef656714a0219605a6a6d (diff)
downloadlibndp-7186b5235eda2ab4b42770f0149d9324fd39d9d2.tar.gz
lib: introduce option validity checks
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
-rw-r--r--libndp/libndp.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/libndp/libndp.c b/libndp/libndp.c
index 4ffe6bb..0bd664e 100644
--- a/libndp/libndp.c
+++ b/libndp/libndp.c
@@ -958,6 +958,7 @@ void ndp_msgra_retransmit_time_set(struct ndp_msgra *msgra,
struct ndp_msg_opt_type_info {
uint8_t raw_type;
+ size_t raw_struct_size;
};
static struct ndp_msg_opt_type_info ndp_msg_opt_type_info_list[] =
@@ -970,15 +971,18 @@ static struct ndp_msg_opt_type_info ndp_msg_opt_type_info_list[] =
},
[NDP_MSG_OPT_PREFIX] = {
.raw_type = ND_OPT_PREFIX_INFORMATION,
+ .raw_struct_size = sizeof(struct nd_opt_prefix_info),
},
[NDP_MSG_OPT_REDIR] = {
.raw_type = ND_OPT_REDIRECTED_HEADER,
},
[NDP_MSG_OPT_MTU] = {
.raw_type = ND_OPT_MTU,
+ .raw_struct_size = sizeof(struct nd_opt_mtu),
},
[NDP_MSG_OPT_ROUTE] = {
.raw_type = __ND_OPT_ROUTE_INFO,
+ .raw_struct_size = sizeof(struct __nd_opt_route_info),
},
};
@@ -989,6 +993,19 @@ struct ndp_msg_opt_type_info *ndp_msg_opt_type_info(enum ndp_msg_opt_type msg_op
return &ndp_msg_opt_type_info_list[msg_opt_type];
}
+struct ndp_msg_opt_type_info *ndp_msg_opt_type_info_by_raw_type(uint8_t raw_type)
+{
+ struct ndp_msg_opt_type_info *info;
+ int i;
+
+ for (i = 0; i < NDP_MSG_OPT_TYPE_LIST_SIZE; i++) {
+ info = &ndp_msg_opt_type_info_list[i];
+ if (info->raw_type == raw_type)
+ return info;
+ }
+ return NULL;
+}
+
/**
* ndp_msg_next_opt_offset:
* @msg: message structure
@@ -1033,6 +1050,34 @@ int ndp_msg_next_opt_offset(struct ndp_msg *msg, int offset,
return -1;
}
+#define __INVALID_OPT_TYPE_MAGIC 0xff
+
+/*
+ * Check for validity of options and mark by magic opt type in case it is not
+ * so ndp_msg_next_opt_offset() will ignore it.
+ */
+static void ndp_msg_check_opts(struct ndp_msg *msg)
+{
+ unsigned char *ptr = ndp_msg_payload_opts(msg);
+ size_t len = ndp_msg_payload_opts_len(msg);
+ struct ndp_msg_opt_type_info *info;
+
+ while (len > 0) {
+ uint8_t cur_opt_raw_type = ptr[0];
+ uint8_t cur_opt_len = ptr[1] << 3; /* convert to bytes */
+
+ if (!cur_opt_len || len < cur_opt_len)
+ break;
+ info = ndp_msg_opt_type_info_by_raw_type(cur_opt_raw_type);
+ if (info) {
+ if (info->raw_struct_size &&
+ cur_opt_len < info->raw_struct_size)
+ ptr[0] = __INVALID_OPT_TYPE_MAGIC;
+ }
+ ptr += cur_opt_len;
+ len -= cur_opt_len;
+ }
+}
/**
* SECTION: msg_opt getters/setters
@@ -1321,6 +1366,8 @@ static int ndp_sock_recv(struct ndp *ndp)
dbg(ndp, "rcvd %s, len: %luB",
ndp_msg_type_info(msg_type)->strabbr, len);
+ ndp_msg_check_opts(msg);
+
err = ndp_call_handlers(ndp, msg);;
free_msg: