From 66e019a6af827a254641e83e96ee36b0f4adc5e3 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Wed, 20 Apr 2011 16:24:07 -0500 Subject: tipc: Strengthen checks for neighboring node discovery Enhances existing checks on the discovery domain associated with a TIPC bearer. A bearer can no longer be configured to accept links from itself only (which would be pointless), or to nodes outside its own cluster (since multi-cluster support has now been removed from TIPC). Also, the neighbor discovery routine now validates link setup requests against the configured discovery domain for the bearer, rather than simply ensuring the requesting node belongs to the node's own cluster. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/bearer.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'net/tipc/bearer.c') diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 411719feb803..f7c29af4ab81 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -493,8 +493,15 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) warn("Bearer <%s> rejected, illegal name\n", name); return -EINVAL; } - if (!tipc_addr_domain_valid(disc_domain) || - !tipc_in_scope(disc_domain, tipc_own_addr)) { + if (tipc_addr_domain_valid(disc_domain) && + (disc_domain != tipc_own_addr)) { + if (tipc_in_scope(disc_domain, tipc_own_addr)) { + disc_domain = tipc_own_addr & TIPC_CLUSTER_MASK; + res = 0; /* accept any node in own cluster */ + } else if (in_own_cluster(disc_domain)) + res = 0; /* accept specified node in own cluster */ + } + if (res) { warn("Bearer <%s> rejected, illegal discovery domain\n", name); return -EINVAL; } -- cgit v1.2.3 From 3a777ff8b14456e15991c9fcc225943453dc3a75 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Thu, 21 Apr 2011 13:58:26 -0500 Subject: tipc: Enhance handling of discovery object creation failures Modifies bearer creation and deletion code to improve handling of scenarios when a neighbor discovery object cannot be created. The creation routine now aborts the creation of a bearer if its discovery object cannot be created, and deletes the newly created bearer, rather than failing quietly and leaving an unusable bearer hanging around. Since the exit via the goto label really isn't a definitive failure in all cases, relabel it appropriately. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/bearer.c | 30 ++++++++++++++++++------------ net/tipc/discover.c | 45 +++++++++++++++++++++------------------------ net/tipc/discover.h | 8 +++----- 3 files changed, 42 insertions(+), 41 deletions(-) (limited to 'net/tipc/bearer.c') diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index f7c29af4ab81..5fcd1c1214fd 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -46,6 +46,8 @@ static u32 media_count; struct tipc_bearer tipc_bearers[MAX_BEARERS]; +static void bearer_disable(struct tipc_bearer *b_ptr); + /** * media_name_valid - validate media name * @@ -518,7 +520,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) if (!m_ptr) { warn("Bearer <%s> rejected, media <%s> not registered\n", name, b_name.media_name); - goto failed; + goto exit; } if (priority == TIPC_MEDIA_LINK_PRI) @@ -534,14 +536,14 @@ restart: } if (!strcmp(name, tipc_bearers[i].name)) { warn("Bearer <%s> rejected, already enabled\n", name); - goto failed; + goto exit; } if ((tipc_bearers[i].priority == priority) && (++with_this_prio > 2)) { if (priority-- == 0) { warn("Bearer <%s> rejected, duplicate priority\n", name); - goto failed; + goto exit; } warn("Bearer <%s> priority adjustment required %u->%u\n", name, priority + 1, priority); @@ -551,7 +553,7 @@ restart: if (bearer_id >= MAX_BEARERS) { warn("Bearer <%s> rejected, bearer limit reached (%u)\n", name, MAX_BEARERS); - goto failed; + goto exit; } b_ptr = &tipc_bearers[bearer_id]; @@ -559,7 +561,7 @@ restart: res = m_ptr->enable_bearer(b_ptr); if (res) { warn("Bearer <%s> rejected, enable failure (%d)\n", name, -res); - goto failed; + goto exit; } b_ptr->identity = bearer_id; @@ -569,14 +571,18 @@ restart: b_ptr->priority = priority; INIT_LIST_HEAD(&b_ptr->cong_links); INIT_LIST_HEAD(&b_ptr->links); - b_ptr->link_req = tipc_disc_init_link_req(b_ptr, &m_ptr->bcast_addr, - disc_domain); spin_lock_init(&b_ptr->lock); - write_unlock_bh(&tipc_net_lock); + + res = tipc_disc_create(b_ptr, &m_ptr->bcast_addr, disc_domain); + if (res) { + bearer_disable(b_ptr); + warn("Bearer <%s> rejected, discovery object creation failed\n", + name); + goto exit; + } info("Enabled bearer <%s>, discovery domain %s, priority %u\n", name, tipc_addr_string_fill(addr_string, disc_domain), priority); - return 0; -failed: +exit: write_unlock_bh(&tipc_net_lock); return res; } @@ -627,14 +633,14 @@ static void bearer_disable(struct tipc_bearer *b_ptr) struct link *temp_l_ptr; info("Disabling bearer <%s>\n", b_ptr->name); - tipc_disc_stop_link_req(b_ptr->link_req); spin_lock_bh(&b_ptr->lock); - b_ptr->link_req = NULL; b_ptr->blocked = 1; b_ptr->media->disable_bearer(b_ptr); list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { tipc_link_delete(l_ptr); } + if (b_ptr->link_req) + tipc_disc_delete(b_ptr->link_req); spin_unlock_bh(&b_ptr->lock); memset(b_ptr, 0, sizeof(struct tipc_bearer)); } diff --git a/net/tipc/discover.c b/net/tipc/discover.c index d2163bd99e59..6acf32a9eef8 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -215,22 +215,6 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) tipc_node_unlock(n_ptr); } -/** - * tipc_disc_stop_link_req - stop sending periodic link setup requests - * @req: ptr to link request structure - */ - -void tipc_disc_stop_link_req(struct link_req *req) -{ - if (!req) - return; - - k_cancel_timer(&req->timer); - k_term_timer(&req->timer); - buf_discard(req->buf); - kfree(req); -} - /** * tipc_disc_update_link_req - update frequency of periodic link setup requests * @req: ptr to link request structure @@ -286,28 +270,27 @@ static void disc_timeout(struct link_req *req) } /** - * tipc_disc_init_link_req - start sending periodic link setup requests + * tipc_disc_create - create object to send periodic link setup requests * @b_ptr: ptr to bearer issuing requests * @dest: destination address for request messages * @dest_domain: network domain to which links can be established * - * Returns pointer to link request structure, or NULL if unable to create. + * Returns 0 if successful, otherwise -errno. */ -struct link_req *tipc_disc_init_link_req(struct tipc_bearer *b_ptr, - const struct tipc_media_addr *dest, - u32 dest_domain) +int tipc_disc_create(struct tipc_bearer *b_ptr, + struct tipc_media_addr *dest, u32 dest_domain) { struct link_req *req; req = kmalloc(sizeof(*req), GFP_ATOMIC); if (!req) - return NULL; + return -ENOMEM; req->buf = tipc_disc_init_msg(DSC_REQ_MSG, dest_domain, b_ptr); if (!req->buf) { kfree(req); - return NULL; + return -ENOMSG; } memcpy(&req->dest, dest, sizeof(*dest)); @@ -316,6 +299,20 @@ struct link_req *tipc_disc_init_link_req(struct tipc_bearer *b_ptr, req->timer_intv = TIPC_LINK_REQ_INIT; k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req); k_start_timer(&req->timer, req->timer_intv); - return req; + b_ptr->link_req = req; + return 0; +} + +/** + * tipc_disc_delete - destroy object sending periodic link setup requests + * @req: ptr to link request structure + */ + +void tipc_disc_delete(struct link_req *req) +{ + k_cancel_timer(&req->timer); + k_term_timer(&req->timer); + buf_discard(req->buf); + kfree(req); } diff --git a/net/tipc/discover.h b/net/tipc/discover.h index e48a167e47b2..d6e44e3dcdbc 100644 --- a/net/tipc/discover.h +++ b/net/tipc/discover.h @@ -39,12 +39,10 @@ struct link_req; -struct link_req *tipc_disc_init_link_req(struct tipc_bearer *b_ptr, - const struct tipc_media_addr *dest, - u32 dest_domain); +int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest, + u32 dest_domain); +void tipc_disc_delete(struct link_req *req); void tipc_disc_update_link_req(struct link_req *req); -void tipc_disc_stop_link_req(struct link_req *req); - void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr); #endif -- cgit v1.2.3 From 1209966cd5d2ec7f89ad2ed58a6a342aa8ea8712 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Thu, 21 Apr 2011 19:05:25 -0500 Subject: tipc: Add monitoring of number of nodes discovered by bearer Augments TIPC's discovery object to track the number of neighboring nodes having an active link to the associated bearer. This means tipc_disc_update_link_req() becomes either one of: tipc_disc_add_dest() or: tipc_disc_remove_dest() depending on the code flow direction of things. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/bearer.c | 4 ++-- net/tipc/discover.c | 32 +++++++++++++++++++++++++++----- net/tipc/discover.h | 3 ++- 3 files changed, 31 insertions(+), 8 deletions(-) (limited to 'net/tipc/bearer.c') diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 5fcd1c1214fd..85209eadfae6 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -344,15 +344,15 @@ struct sk_buff *tipc_bearer_get_names(void) void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest) { tipc_nmap_add(&b_ptr->nodes, dest); - tipc_disc_update_link_req(b_ptr->link_req); tipc_bcbearer_sort(); + tipc_disc_add_dest(b_ptr->link_req); } void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest) { tipc_nmap_remove(&b_ptr->nodes, dest); - tipc_disc_update_link_req(b_ptr->link_req); tipc_bcbearer_sort(); + tipc_disc_remove_dest(b_ptr->link_req); } /* diff --git a/net/tipc/discover.c b/net/tipc/discover.c index dba47673124d..3cb232d1f5dc 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -53,6 +53,7 @@ * @bearer: bearer issuing requests * @dest: destination address for request messages * @domain: network domain to which links can be established + * @num_nodes: number of nodes currently discovered (i.e. with an active link) * @buf: request message to be (repeatedly) sent * @timer: timer governing period between requests * @timer_intv: current interval between requests (in ms) @@ -61,6 +62,7 @@ struct link_req { struct tipc_bearer *bearer; struct tipc_media_addr dest; u32 domain; + int num_nodes; struct sk_buff *buf; struct timer_list timer; unsigned int timer_intv; @@ -216,15 +218,12 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) } /** - * tipc_disc_update_link_req - update frequency of periodic link setup requests + * disc_update - update frequency of periodic link setup requests * @req: ptr to link request structure */ -void tipc_disc_update_link_req(struct link_req *req) +static void disc_update(struct link_req *req) { - if (!req) - return; - if (req->timer_intv == TIPC_LINK_REQ_SLOW) { if (!req->bearer->nodes.count) { req->timer_intv = TIPC_LINK_REQ_FAST; @@ -240,6 +239,28 @@ void tipc_disc_update_link_req(struct link_req *req) } } +/** + * tipc_disc_add_dest - increment set of discovered nodes + * @req: ptr to link request structure + */ + +void tipc_disc_add_dest(struct link_req *req) +{ + req->num_nodes++; + disc_update(req); +} + +/** + * tipc_disc_remove_dest - decrement set of discovered nodes + * @req: ptr to link request structure + */ + +void tipc_disc_remove_dest(struct link_req *req) +{ + req->num_nodes--; + disc_update(req); +} + /** * disc_send_msg - send link setup request message * @req: ptr to link request structure @@ -307,6 +328,7 @@ int tipc_disc_create(struct tipc_bearer *b_ptr, memcpy(&req->dest, dest, sizeof(*dest)); req->bearer = b_ptr; req->domain = dest_domain; + req->num_nodes = 0; req->timer_intv = TIPC_LINK_REQ_INIT; k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req); k_start_timer(&req->timer, req->timer_intv); diff --git a/net/tipc/discover.h b/net/tipc/discover.h index d6e44e3dcdbc..a3af595b86cb 100644 --- a/net/tipc/discover.h +++ b/net/tipc/discover.h @@ -42,7 +42,8 @@ struct link_req; int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest, u32 dest_domain); void tipc_disc_delete(struct link_req *req); -void tipc_disc_update_link_req(struct link_req *req); +void tipc_disc_add_dest(struct link_req *req); +void tipc_disc_remove_dest(struct link_req *req); void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr); #endif -- cgit v1.2.3