diff options
Diffstat (limited to 'net/tipc/msg.c')
| -rw-r--r-- | net/tipc/msg.c | 94 | 
1 files changed, 94 insertions, 0 deletions
| diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 73dcd00d674..381063817b4 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -40,6 +40,100 @@  #include "msg.h"  #include "bearer.h" +u32 tipc_msg_tot_importance(struct tipc_msg *m) +{ +	if (likely(msg_isdata(m))) { +		if (likely(msg_orignode(m) == tipc_own_addr)) +			return msg_importance(m); +		return msg_importance(m) + 4; +	} +	if ((msg_user(m) == MSG_FRAGMENTER)  && +	    (msg_type(m) == FIRST_FRAGMENT)) +		return msg_importance(msg_get_wrapped(m)); +	return msg_importance(m); +} + + +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); +	if (!msg_short(m)) { +		msg_set_orignode(m, tipc_own_addr); +		msg_set_destnode(m, destnode); +	} +} + +/** + * tipc_msg_calc_data_size - determine total data size for message + */ + +int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect) +{ +	int dsz = 0; +	int i; + +	for (i = 0; i < num_sect; i++) +		dsz += msg_sect[i].iov_len; +	return dsz; +} + +/** + * tipc_msg_build - create message using specified header and data + * + * Note: Caller must not hold any locks in case copy_from_user() is interrupted! + * + * Returns message data size or errno + */ + +int tipc_msg_build(struct tipc_msg *hdr, +			    struct iovec const *msg_sect, u32 num_sect, +			    int max_size, int usrmem, struct sk_buff** buf) +{ +	int dsz, sz, hsz, pos, res, cnt; + +	dsz = tipc_msg_calc_data_size(msg_sect, num_sect); +	if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) { +		*buf = NULL; +		return -EINVAL; +	} + +	pos = hsz = msg_hdr_sz(hdr); +	sz = hsz + dsz; +	msg_set_size(hdr, sz); +	if (unlikely(sz > max_size)) { +		*buf = NULL; +		return dsz; +	} + +	*buf = buf_acquire(sz); +	if (!(*buf)) +		return -ENOMEM; +	skb_copy_to_linear_data(*buf, hdr, hsz); +	for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) { +		if (likely(usrmem)) +			res = !copy_from_user((*buf)->data + pos, +					      msg_sect[cnt].iov_base, +					      msg_sect[cnt].iov_len); +		else +			skb_copy_to_linear_data_offset(*buf, pos, +						       msg_sect[cnt].iov_base, +						       msg_sect[cnt].iov_len); +		pos += msg_sect[cnt].iov_len; +	} +	if (likely(res)) +		return dsz; + +	buf_discard(*buf); +	*buf = NULL; +	return -EFAULT; +}  #ifdef CONFIG_TIPC_DEBUG | 
