static void net_route_named_msg(struct sk_buff *buf) { struct tipc_msg *msg = buf_msg(buf); u32 dnode; u32 dport; if (!msg_named(msg)) { msg_dbg(msg, "tipc_net->drop_nam:"); buf_discard(buf); return; } dnode = addr_domain(msg_lookup_scope(msg)); dport = tipc_nametbl_translate(msg_nametype(msg), msg_nameinst(msg), &dnode); dbg("tipc_net->lookup<%u,%u>-><%u,%x>\n", msg_nametype(msg), msg_nameinst(msg), dport, dnode); if (dport) { msg_set_destnode(msg, dnode); msg_set_destport(msg, dport); tipc_net_route_msg(buf); return; } msg_dbg(msg, "tipc_net->rej:NO NAME: "); tipc_reject_msg(buf, TIPC_ERR_NO_NAME); }
/** * tipc_msg_eval: determine fate of message that found no destination * @buf: the buffer containing the message. * @dnode: return value: next-hop node, if message to be forwarded * @err: error code to use, if message to be rejected * * Does not consume buffer * Returns 0 (TIPC_OK) if message ok and we can try again, -TIPC error * code if message to be rejected */ int tipc_msg_eval(struct sk_buff *buf, u32 *dnode) { struct tipc_msg *msg = buf_msg(buf); u32 dport; if (msg_type(msg) != TIPC_NAMED_MSG) return -TIPC_ERR_NO_PORT; if (skb_linearize(buf)) return -TIPC_ERR_NO_NAME; if (msg_data_sz(msg) > MAX_FORWARD_SIZE) return -TIPC_ERR_NO_NAME; if (msg_reroute_cnt(msg) > 0) return -TIPC_ERR_NO_NAME; *dnode = addr_domain(msg_lookup_scope(msg)); dport = tipc_nametbl_translate(msg_nametype(msg), msg_nameinst(msg), dnode); if (!dport) return -TIPC_ERR_NO_NAME; msg_incr_reroute_cnt(msg); msg_set_destnode(msg, *dnode); msg_set_destport(msg, dport); return TIPC_OK; }
/** * tipc_msg_reverse(): swap source and destination addresses and add error code * @buf: buffer containing message to be reversed * @dnode: return value: node where to send message after reversal * @err: error code to be set in message * Consumes buffer if failure * Returns true if success, otherwise false */ bool tipc_msg_reverse(struct sk_buff *buf, u32 *dnode, int err) { struct tipc_msg *msg = buf_msg(buf); uint imp = msg_importance(msg); struct tipc_msg ohdr; uint rdsz = min_t(uint, msg_data_sz(msg), MAX_FORWARD_SIZE); if (skb_linearize(buf)) goto exit; if (msg_dest_droppable(msg)) goto exit; if (msg_errcode(msg)) goto exit; memcpy(&ohdr, msg, msg_hdr_sz(msg)); imp = min_t(uint, imp + 1, TIPC_CRITICAL_IMPORTANCE); if (msg_isdata(msg)) msg_set_importance(msg, imp); msg_set_errcode(msg, err); msg_set_origport(msg, msg_destport(&ohdr)); msg_set_destport(msg, msg_origport(&ohdr)); msg_set_prevnode(msg, tipc_own_addr); if (!msg_short(msg)) { msg_set_orignode(msg, msg_destnode(&ohdr)); msg_set_destnode(msg, msg_orignode(&ohdr)); } msg_set_size(msg, msg_hdr_sz(msg) + rdsz); skb_trim(buf, msg_size(msg)); skb_orphan(buf); *dnode = msg_orignode(&ohdr); return true; exit: kfree_skb(buf); return false; }
static void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf, u32 lower, u32 upper) { struct sk_buff *buf_copy; struct tipc_node *n_ptr; u32 n_num; u32 tstop; assert(lower <= upper); assert(((lower >= 1) && (lower <= tipc_max_nodes)) || ((lower >= LOWEST_SLAVE) && (lower <= tipc_highest_allowed_slave))); assert(((upper >= 1) && (upper <= tipc_max_nodes)) || ((upper >= LOWEST_SLAVE) && (upper <= tipc_highest_allowed_slave))); assert(in_own_cluster(c_ptr->addr)); tstop = is_slave(upper) ? c_ptr->highest_slave : c_ptr->highest_node; if (tstop > upper) tstop = upper; for (n_num = lower; n_num <= tstop; n_num++) { n_ptr = c_ptr->nodes[n_num]; if (n_ptr && tipc_node_has_active_links(n_ptr)) { buf_copy = skb_copy(buf, GFP_ATOMIC); if (buf_copy == NULL) break; msg_set_destnode(buf_msg(buf_copy), n_ptr->addr); tipc_link_send(buf_copy, n_ptr->addr, n_ptr->addr); } } buf_discard(buf); }
void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, u32 destnode) { memset(m, 0, hsize); msg_set_version(m); msg_set_user(m, user); msg_set_hdr_sz(m, hsize); msg_set_size(m, hsize); msg_set_prevnode(m, tipc_own_addr); msg_set_type(m, type); msg_set_orignode(m, tipc_own_addr); msg_set_destnode(m, destnode); }
static void net_route_named_msg(struct sk_buff *buf) { struct tipc_msg *msg = buf_msg(buf); u32 dnode; u32 dport; if (!msg_named(msg)) { kfree_skb(buf); return; } dnode = addr_domain(msg_lookup_scope(msg)); dport = tipc_nametbl_translate(msg_nametype(msg), msg_nameinst(msg), &dnode); if (dport) { msg_set_destnode(msg, dnode); msg_set_destport(msg, dport); tipc_net_route_msg(buf); return; } tipc_reject_msg(buf, TIPC_ERR_NO_NAME); }
void tipc_cltr_broadcast(struct sk_buff *buf) { struct sk_buff *buf_copy; struct cluster *c_ptr; struct tipc_node *n_ptr; u32 n_num; u32 tstart; u32 tstop; u32 node_type; if (tipc_mode == TIPC_NET_MODE) { c_ptr = tipc_cltr_find(tipc_own_addr); assert(in_own_cluster(c_ptr->addr)); /* For now */ /* Send to standard nodes, then repeat loop sending to slaves */ tstart = 1; tstop = c_ptr->highest_node; for (node_type = 1; node_type <= 2; node_type++) { for (n_num = tstart; n_num <= tstop; n_num++) { n_ptr = c_ptr->nodes[n_num]; if (n_ptr && tipc_node_has_active_links(n_ptr)) { buf_copy = skb_copy(buf, GFP_ATOMIC); if (buf_copy == NULL) goto exit; msg_set_destnode(buf_msg(buf_copy), n_ptr->addr); tipc_link_send(buf_copy, n_ptr->addr, n_ptr->addr); } } tstart = LOWEST_SLAVE; tstop = c_ptr->highest_slave; } } exit: buf_discard(buf); }
struct sk_buff *tipc_msg_create(uint user, uint type, uint hdr_sz, uint data_sz, u32 dnode, u32 onode, u32 dport, u32 oport, int errcode) { struct tipc_msg *msg; struct sk_buff *buf; buf = tipc_buf_acquire(hdr_sz + data_sz); if (unlikely(!buf)) return NULL; msg = buf_msg(buf); tipc_msg_init(msg, user, type, hdr_sz, dnode); msg_set_size(msg, hdr_sz + data_sz); msg_set_prevnode(msg, onode); msg_set_origport(msg, oport); msg_set_destport(msg, dport); msg_set_errcode(msg, errcode); if (hdr_sz > SHORT_H_SIZE) { msg_set_orignode(msg, onode); msg_set_destnode(msg, dnode); } return buf; }