Commit 1d70ec70 authored by David S. Miller's avatar David S. Miller

Merge branch 'tipc'

Jon Maloy says:

====================
tipc: clean up socket message reception

Despite recent improvements the message reception code in socket.c is
perceived as obscure and hard to follow, especially regarding the logics
for message rejection. With the commits in this series we try to remedy
this situation.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a69e5a0d cda3696d
...@@ -463,60 +463,72 @@ bool tipc_msg_make_bundle(struct sk_buff **skb, struct tipc_msg *msg, ...@@ -463,60 +463,72 @@ bool tipc_msg_make_bundle(struct sk_buff **skb, struct tipc_msg *msg,
/** /**
* tipc_msg_reverse(): swap source and destination addresses and add error code * tipc_msg_reverse(): swap source and destination addresses and add error code
* @buf: buffer containing message to be reversed * @own_node: originating node id for reversed message
* @dnode: return value: node where to send message after reversal * @skb: buffer containing message to be reversed; may be replaced.
* @err: error code to be set in message * @err: error code to be set in message, if any
* Consumes buffer if failure * Consumes buffer at failure
* Returns true if success, otherwise false * Returns true if success, otherwise false
*/ */
bool tipc_msg_reverse(u32 own_addr, struct sk_buff *buf, u32 *dnode, bool tipc_msg_reverse(u32 own_node, struct sk_buff **skb, int err)
int err)
{ {
struct tipc_msg *msg = buf_msg(buf); struct sk_buff *_skb = *skb;
struct tipc_msg *hdr = buf_msg(_skb);
struct tipc_msg ohdr; struct tipc_msg ohdr;
uint rdsz = min_t(uint, msg_data_sz(msg), MAX_FORWARD_SIZE); int dlen = min_t(uint, msg_data_sz(hdr), MAX_FORWARD_SIZE);
if (skb_linearize(buf)) if (skb_linearize(_skb))
goto exit; goto exit;
msg = buf_msg(buf); hdr = buf_msg(_skb);
if (msg_dest_droppable(msg)) if (msg_dest_droppable(hdr))
goto exit; goto exit;
if (msg_errcode(msg)) if (msg_errcode(hdr))
goto exit; goto exit;
memcpy(&ohdr, msg, msg_hdr_sz(msg));
msg_set_errcode(msg, err); /* Take a copy of original header before altering message */
msg_set_origport(msg, msg_destport(&ohdr)); memcpy(&ohdr, hdr, msg_hdr_sz(hdr));
msg_set_destport(msg, msg_origport(&ohdr));
msg_set_prevnode(msg, own_addr); /* Never return SHORT header; expand by replacing buffer if necessary */
if (!msg_short(msg)) { if (msg_short(hdr)) {
msg_set_orignode(msg, msg_destnode(&ohdr)); *skb = tipc_buf_acquire(BASIC_H_SIZE + dlen);
msg_set_destnode(msg, msg_orignode(&ohdr)); if (!*skb)
goto exit;
memcpy((*skb)->data + BASIC_H_SIZE, msg_data(hdr), dlen);
kfree_skb(_skb);
_skb = *skb;
hdr = buf_msg(_skb);
memcpy(hdr, &ohdr, BASIC_H_SIZE);
msg_set_hdr_sz(hdr, BASIC_H_SIZE);
} }
msg_set_size(msg, msg_hdr_sz(msg) + rdsz);
skb_trim(buf, msg_size(msg)); /* Now reverse the concerned fields */
skb_orphan(buf); msg_set_errcode(hdr, err);
*dnode = msg_orignode(&ohdr); msg_set_origport(hdr, msg_destport(&ohdr));
msg_set_destport(hdr, msg_origport(&ohdr));
msg_set_destnode(hdr, msg_prevnode(&ohdr));
msg_set_prevnode(hdr, own_node);
msg_set_orignode(hdr, own_node);
msg_set_size(hdr, msg_hdr_sz(hdr) + dlen);
skb_trim(_skb, msg_size(hdr));
skb_orphan(_skb);
return true; return true;
exit: exit:
kfree_skb(buf); kfree_skb(_skb);
*dnode = 0; *skb = NULL;
return false; return false;
} }
/** /**
* tipc_msg_lookup_dest(): try to find new destination for named message * tipc_msg_lookup_dest(): try to find new destination for named message
* @skb: the buffer containing the message. * @skb: the buffer containing the message.
* @dnode: return value: next-hop node, if destination found * @err: error code to be used by caller if lookup fails
* @err: return value: error code to use, if message to be rejected
* Does not consume buffer * Does not consume buffer
* Returns true if a destination is found, false otherwise * Returns true if a destination is found, false otherwise
*/ */
bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err)
u32 *dnode, int *err)
{ {
struct tipc_msg *msg = buf_msg(skb); struct tipc_msg *msg = buf_msg(skb);
u32 dport; u32 dport, dnode;
u32 own_addr = tipc_own_addr(net); u32 onode = tipc_own_addr(net);
if (!msg_isdata(msg)) if (!msg_isdata(msg))
return false; return false;
...@@ -529,15 +541,15 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, ...@@ -529,15 +541,15 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb,
return false; return false;
if (msg_reroute_cnt(msg)) if (msg_reroute_cnt(msg))
return false; return false;
*dnode = addr_domain(net, msg_lookup_scope(msg)); dnode = addr_domain(net, msg_lookup_scope(msg));
dport = tipc_nametbl_translate(net, msg_nametype(msg), dport = tipc_nametbl_translate(net, msg_nametype(msg),
msg_nameinst(msg), dnode); msg_nameinst(msg), &dnode);
if (!dport) if (!dport)
return false; return false;
msg_incr_reroute_cnt(msg); msg_incr_reroute_cnt(msg);
if (*dnode != own_addr) if (dnode != onode)
msg_set_prevnode(msg, own_addr); msg_set_prevnode(msg, onode);
msg_set_destnode(msg, *dnode); msg_set_destnode(msg, dnode);
msg_set_destport(msg, dport); msg_set_destport(msg, dport);
*err = TIPC_OK; *err = TIPC_OK;
return true; return true;
......
...@@ -785,8 +785,7 @@ static inline bool msg_peer_is_up(struct tipc_msg *m) ...@@ -785,8 +785,7 @@ static inline bool msg_peer_is_up(struct tipc_msg *m)
struct sk_buff *tipc_buf_acquire(u32 size); struct sk_buff *tipc_buf_acquire(u32 size);
bool tipc_msg_validate(struct sk_buff *skb); bool tipc_msg_validate(struct sk_buff *skb);
bool tipc_msg_reverse(u32 own_addr, struct sk_buff *buf, u32 *dnode, bool tipc_msg_reverse(u32 own_addr, struct sk_buff **skb, int err);
int err);
void tipc_msg_init(u32 own_addr, struct tipc_msg *m, u32 user, u32 type, void tipc_msg_init(u32 own_addr, struct tipc_msg *m, u32 user, u32 type,
u32 hsize, u32 destnode); u32 hsize, u32 destnode);
struct sk_buff *tipc_msg_create(uint user, uint type, uint hdr_sz, struct sk_buff *tipc_msg_create(uint user, uint type, uint hdr_sz,
...@@ -799,8 +798,7 @@ bool tipc_msg_make_bundle(struct sk_buff **skb, struct tipc_msg *msg, ...@@ -799,8 +798,7 @@ bool tipc_msg_make_bundle(struct sk_buff **skb, struct tipc_msg *msg,
bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos); bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos);
int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m,
int offset, int dsz, int mtu, struct sk_buff_head *list); int offset, int dsz, int mtu, struct sk_buff_head *list);
bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, u32 *dnode, bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err);
int *err);
struct sk_buff *tipc_msg_reassemble(struct sk_buff_head *list); struct sk_buff *tipc_msg_reassemble(struct sk_buff_head *list);
static inline u16 buf_seqno(struct sk_buff *skb) static inline u16 buf_seqno(struct sk_buff *skb)
......
This diff is collapsed.
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
SKB_TRUESIZE(TIPC_MAX_USER_MSG_SIZE)) SKB_TRUESIZE(TIPC_MAX_USER_MSG_SIZE))
int tipc_socket_init(void); int tipc_socket_init(void);
void tipc_socket_stop(void); void tipc_socket_stop(void);
int tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq); void tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq);
void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq, void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,
struct sk_buff_head *inputq); struct sk_buff_head *inputq);
void tipc_sk_reinit(struct net *net); void tipc_sk_reinit(struct net *net);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment