diff options
author | Jiri Pirko <jiri@resnulli.us> | 2013-03-16 16:44:49 +0100 |
---|---|---|
committer | Jiri Pirko <jiri@resnulli.us> | 2013-03-17 11:11:48 +0100 |
commit | 37d1f82396af8b67e604c6a207ce28a03aca6f1d (patch) | |
tree | 716c383c2e2d5b8d0c566b268d766ac21fe17819 /libndp | |
parent | 04c2d9d32a7dad6a4830bca132fc4ca72b276ac6 (diff) | |
download | libndp-37d1f82396af8b67e604c6a207ce28a03aca6f1d.tar.gz |
lib: do not parse packet right away but do rather for every getter
Vice versa for setters.
Also store pointer to opts area and use type_infos to set that pointer
correctly.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Diffstat (limited to 'libndp')
-rw-r--r-- | libndp/libndp.c | 142 |
1 files changed, 102 insertions, 40 deletions
diff --git a/libndp/libndp.c b/libndp/libndp.c index d1a2c46..54c390f 100644 --- a/libndp/libndp.c +++ b/libndp/libndp.c @@ -234,13 +234,7 @@ struct ndp_msgrs { }; struct ndp_msgra { - uint8_t curhoplimit; - bool flag_managed; - bool flag_other; - bool flag_home_agent; - uint16_t router_lifetime; - uint32_t reachable_time; - uint32_t retransmit_time; + struct nd_router_advert *ra; struct { bool present; unsigned char addr[ETH_ALEN]; @@ -276,7 +270,7 @@ struct ndp_msgra { NDP_EXPORT uint8_t ndp_msgra_curhoplimit(struct ndp_msgra *msgra) { - return msgra->curhoplimit; + return msgra->ra->nd_ra_curhoplimit; } /** @@ -288,7 +282,7 @@ uint8_t ndp_msgra_curhoplimit(struct ndp_msgra *msgra) NDP_EXPORT void ndp_msgra_curhoplimit_set(struct ndp_msgra *msgra, uint8_t curhoplimit) { - msgra->curhoplimit = curhoplimit; + msgra->ra->nd_ra_curhoplimit = curhoplimit; } /** @@ -302,7 +296,7 @@ void ndp_msgra_curhoplimit_set(struct ndp_msgra *msgra, uint8_t curhoplimit) NDP_EXPORT bool ndp_msgra_flag_managed(struct ndp_msgra *msgra) { - return msgra->flag_managed; + return msgra->ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED; } /** @@ -314,7 +308,10 @@ bool ndp_msgra_flag_managed(struct ndp_msgra *msgra) NDP_EXPORT void ndp_msgra_flag_managed_set(struct ndp_msgra *msgra, bool flag_managed) { - msgra->flag_managed = flag_managed; + if (flag_managed) + msgra->ra->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED; + else + msgra->ra->nd_ra_flags_reserved &= ~ND_RA_FLAG_MANAGED; } /** @@ -328,7 +325,7 @@ void ndp_msgra_flag_managed_set(struct ndp_msgra *msgra, bool flag_managed) NDP_EXPORT bool ndp_msgra_flag_other(struct ndp_msgra *msgra) { - return msgra->flag_other; + return msgra->ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER; } /** @@ -340,7 +337,10 @@ bool ndp_msgra_flag_other(struct ndp_msgra *msgra) NDP_EXPORT void ndp_msgra_flag_other_set(struct ndp_msgra *msgra, bool flag_other) { - msgra->flag_other = flag_other; + if (flag_other) + msgra->ra->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER; + else + msgra->ra->nd_ra_flags_reserved &= ~ND_RA_FLAG_OTHER; } /** @@ -354,7 +354,7 @@ void ndp_msgra_flag_other_set(struct ndp_msgra *msgra, bool flag_other) NDP_EXPORT bool ndp_msgra_flag_home_agent(struct ndp_msgra *msgra) { - return msgra->flag_home_agent; + return msgra->ra->nd_ra_flags_reserved & ND_RA_FLAG_HOME_AGENT; } /** @@ -367,7 +367,10 @@ NDP_EXPORT void ndp_msgra_flag_home_agent_set(struct ndp_msgra *msgra, bool flag_home_agent) { - msgra->flag_home_agent = flag_home_agent; + if (flag_home_agent) + msgra->ra->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT; + else + msgra->ra->nd_ra_flags_reserved &= ~ND_RA_FLAG_HOME_AGENT; } /** @@ -381,7 +384,7 @@ void ndp_msgra_flag_home_agent_set(struct ndp_msgra *msgra, NDP_EXPORT uint16_t ndp_msgra_router_lifetime(struct ndp_msgra *msgra) { - return msgra->router_lifetime; + return ntohs(msgra->ra->nd_ra_router_lifetime); } /** @@ -394,7 +397,7 @@ NDP_EXPORT void ndp_msgra_router_lifetime_set(struct ndp_msgra *msgra, uint16_t router_lifetime) { - msgra->router_lifetime = router_lifetime; + msgra->ra->nd_ra_router_lifetime = htons(router_lifetime); } /** @@ -408,7 +411,7 @@ void ndp_msgra_router_lifetime_set(struct ndp_msgra *msgra, NDP_EXPORT uint32_t ndp_msgra_reachable_time(struct ndp_msgra *msgra) { - return msgra->reachable_time; + return ntohl(msgra->ra->nd_ra_reachable); } /** @@ -421,7 +424,7 @@ NDP_EXPORT void ndp_msgra_reachable_time_set(struct ndp_msgra *msgra, uint32_t reachable_time) { - msgra->reachable_time = reachable_time; + msgra->ra->nd_ra_reachable = htonl(reachable_time); } /** @@ -435,7 +438,7 @@ void ndp_msgra_reachable_time_set(struct ndp_msgra *msgra, NDP_EXPORT uint32_t ndp_msgra_retransmit_time(struct ndp_msgra *msgra) { - return msgra->retransmit_time; + return ntohl(msgra->ra->nd_ra_retransmit); } /** @@ -448,7 +451,7 @@ NDP_EXPORT void ndp_msgra_retransmit_time_set(struct ndp_msgra *msgra, uint32_t retransmit_time) { - msgra->retransmit_time = retransmit_time; + msgra->ra->nd_ra_retransmit = htonl(retransmit_time); } /** @@ -657,6 +660,8 @@ struct ndp_msg { struct in6_addr addrto; uint32_t ifindex; enum ndp_msg_type type; + unsigned char * opts_start; /* pointer to buf at the + place where opts start */ union { struct ndp_msgrs rs; struct ndp_msgra ra; @@ -666,6 +671,35 @@ struct ndp_msg { } nd_msg; }; +struct ndp_msg_type_info { + uint8_t raw_type; + size_t raw_struct_size; +}; + +static struct ndp_msg_type_info ndp_msg_type_infos[] = +{ + [NDP_MSG_RS] = { + .raw_type = ND_ROUTER_SOLICIT, + .raw_struct_size = sizeof(struct nd_router_solicit), + }, + [NDP_MSG_RA] = { + .raw_type = ND_ROUTER_ADVERT, + .raw_struct_size = sizeof(struct nd_router_advert), + }, + [NDP_MSG_NS] = { + .raw_type = ND_NEIGHBOR_SOLICIT, + .raw_struct_size = sizeof(struct nd_neighbor_solicit), + }, + [NDP_MSG_NA] = { + .raw_type = ND_NEIGHBOR_ADVERT, + .raw_struct_size = sizeof(struct nd_neighbor_advert), + }, + [NDP_MSG_R] = { + .raw_type = ND_REDIRECT, + .raw_struct_size = sizeof(struct nd_redirect), + }, +}; + static struct ndp_msg *ndp_msg_alloc(void) { struct ndp_msg *msg; @@ -677,6 +711,14 @@ static struct ndp_msg *ndp_msg_alloc(void) return msg; } +static void ndp_msg_init(struct ndp_msg *msg, enum ndp_msg_type msg_type) +{ + struct ndp_msg_type_info *type_info = &ndp_msg_type_infos[msg_type]; + + msg->type = msg_type; + msg->opts_start = msg->buf + type_info->raw_struct_size; +} + /** * ndp_msg_new: * @p_msg: pointer where new message structure address will be stored @@ -696,7 +738,7 @@ int ndp_msg_new(struct ndp_msg **p_msg, enum ndp_msg_type msg_type) msg = ndp_msg_alloc(); if (!msg) return -ENOMEM; - msg->type = msg_type; + ndp_msg_init(msg, msg_type); return 0; } @@ -743,7 +785,7 @@ size_t ndp_msg_payload_len(struct ndp_msg *msg) * ndp_msg_payload_len_set: * @msg: message structure * - * Set raw Neighbour discovery packet part from the message data length. + * Set raw Neighbour discovery packet data length. **/ NDP_EXPORT void ndp_msg_payload_len_set(struct ndp_msg *msg, size_t len) @@ -754,6 +796,34 @@ void ndp_msg_payload_len_set(struct ndp_msg *msg, size_t len) } /** + * ndp_msg_payload_opts: + * @msg: message structure + * + * Get raw Neighbour discovery packet options part data. + * + * Returns: pointer to raw data. + **/ +NDP_EXPORT +void *ndp_msg_payload_opts(struct ndp_msg *msg) +{ + return msg->opts_start; +} + +/** + * ndp_msg_payload_opts_len: + * @msg: message structure + * + * Get raw Neighbour discovery packet options part data length. + * + * Returns: length in bytes. + **/ +NDP_EXPORT +size_t ndp_msg_payload_opts_len(struct ndp_msg *msg) +{ + return msg->len - (msg->opts_start - msg->buf); +} + +/** * ndp_msgrs: * @msg: message structure * @@ -930,26 +1000,18 @@ static int ndp_process_ra_opt(struct ndp_msgra *msgra, unsigned char *opt_data, static int ndp_process_ra(struct ndp *ndp, struct ndp_msg *msg) { struct ndp_msgra *msgra = ndp_msgra(msg); - struct nd_router_advert *ra = ndp_msg_payload(msg); size_t len = ndp_msg_payload_len(msg); unsigned char *ptr; dbg(ndp, "rcvd RA, len: %luB", len); - if (len < sizeof(*ra)) { + if (len < sizeof(msgra->ra)) { warn(ndp, "rcvd RA packet too short (%luB)", len); return 0; } - msgra->curhoplimit = ra->nd_ra_curhoplimit; - msgra->flag_managed = ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED; - msgra->flag_other = ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER; - msgra->flag_home_agent = ra->nd_ra_flags_reserved & ND_RA_FLAG_HOME_AGENT; - msgra->router_lifetime = ntohs(ra->nd_ra_router_lifetime); - msgra->reachable_time = ntohl(ra->nd_ra_reachable); - msgra->retransmit_time = ntohl(ra->nd_ra_retransmit); - - ptr = ((unsigned char *) ra) + sizeof(*ra); - len -= sizeof(ra); + msgra->ra = ndp_msg_payload(msg); + ptr = ndp_msg_payload_opts(msg); + len = ndp_msg_payload_opts_len(msg); while (len > 0) { int err; uint8_t opt_type = ptr[0]; @@ -1028,22 +1090,22 @@ static int ndp_sock_recv(struct ndp *ndp) err = 0; switch (icmp6_hdr->icmp6_type) { case ND_ROUTER_SOLICIT: - msg->type = NDP_MSG_RS; + ndp_msg_init(msg, NDP_MSG_RS); err = ndp_process_rs(ndp, msg); break; case ND_ROUTER_ADVERT: - msg->type = NDP_MSG_RA; + ndp_msg_init(msg, NDP_MSG_RA); err = ndp_process_ra(ndp, msg); break; case ND_NEIGHBOR_SOLICIT: - msg->type = NDP_MSG_NS; + ndp_msg_init(msg, NDP_MSG_NS); err = ndp_process_ns(ndp, msg); break; case ND_NEIGHBOR_ADVERT: - msg->type = NDP_MSG_NA; + ndp_msg_init(msg, NDP_MSG_NA); err = ndp_process_na(ndp, msg); case ND_REDIRECT: - msg->type = NDP_MSG_R; + ndp_msg_init(msg, NDP_MSG_R); err = ndp_process_r(ndp, msg); break; } |