Commit 61a46dc9 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (42 commits)
  [IOAT]: Do not dereference THIS_MODULE directly to set unsafe.
  [NETROM]: Fix possible null pointer dereference.
  [NET] netpoll: break recursive loop in netpoll rx path
  [NET] netpoll: don't spin forever sending to stopped queues
  [IRDA]: add some IBM think pads
  [ATM]: atm/mpc.c warning fix
  [NET]: skb_find_text ignores to argument
  [NET]: make net/core/dev.c:netdev_nit static
  [NET]: Fix GSO problems in dev_hard_start_xmit()
  [NET]: Fix CHECKSUM_HW GSO problems.
  [TIPC]: Fix incorrect correction to discovery timer frequency computation.
  [TIPC]: Get rid of dynamically allocated arrays in broadcast code.
  [TIPC]: Fixed link switchover bugs
  [TIPC]: Enhanced & cleaned up system messages; fixed 2 obscure memory leaks.
  [TIPC]: First phase of assert() cleanup
  [TIPC]: Disallow config operations that aren't supported in certain modes.
  [TIPC]: Fixed memory leak in tipc_link_send() when destination is unreachable
  [TIPC]: Added missing warning for out-of-memory condition
  [TIPC]: Withdrawing all names from nameless port now returns success, not error
  [TIPC]: Optimized argument validation done by connect().
  ...
parents b78709cf 8070b2b1
......@@ -824,10 +824,9 @@ static int __init ioat_init_module(void)
{
/* it's currently unsafe to unload this module */
/* if forced, worst case is that rmmod hangs */
if (THIS_MODULE != NULL)
THIS_MODULE->unsafe = 1;
__unsafe(THIS_MODULE);
return pci_module_init(&ioat_pci_drv);
pci_module_init(&ioat_pci_drv);
}
module_init(ioat_init_module);
......
......@@ -115,7 +115,11 @@ static nsc_chip_t chips[] = {
/* Contributed by Jan Frey - IBM A30/A31 */
{ "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff,
nsc_ircc_probe_39x, nsc_ircc_init_39x },
{ "IBM", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff,
/* IBM ThinkPads using PC8738x (T60/X60/Z60) */
{ "IBM-PC8738x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff,
nsc_ircc_probe_39x, nsc_ircc_init_39x },
/* IBM ThinkPads using PC8394T (T43/R52/?) */
{ "IBM-PC8394T", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf9, 0xff,
nsc_ircc_probe_39x, nsc_ircc_init_39x },
{ NULL }
};
......
......@@ -699,7 +699,6 @@ extern int dev_hard_start_xmit(struct sk_buff *skb,
extern void dev_init(void);
extern int netdev_nit;
extern int netdev_budget;
/* Called by rtnetlink.c:rtnl_unlock() */
......
......@@ -31,6 +31,7 @@ struct netpoll_info {
int rx_flags;
spinlock_t rx_lock;
struct netpoll *rx_np; /* netpoll that registered an rx_hook */
struct sk_buff_head arp_tx; /* list of arp requests to reply to */
};
void netpoll_poll(struct netpoll *np);
......
......@@ -49,10 +49,18 @@
#define TIPC_MEDIA_TYPE_ETH 1
/*
* Destination address structure used by TIPC bearers when sending messages
*
* IMPORTANT: The fields of this structure MUST be stored using the specified
* byte order indicated below, as the structure is exchanged between nodes
* as part of a link setup process.
*/
struct tipc_media_addr {
__u32 type;
__u32 type; /* bearer type (network byte order) */
union {
__u8 eth_addr[6]; /* Ethernet bearer */
__u8 eth_addr[6]; /* 48 bit Ethernet addr (byte array) */
#if 0
/* Prototypes for other possible bearer types */
......
......@@ -1113,10 +1113,9 @@ static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_clien
static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc)
{
unsigned char *ip;
uint32_t dst_ip = msg->content.in_info.in_dst_ip;
in_cache_entry *entry = mpc->in_ops->get(dst_ip, mpc);
dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc->dev->name, NIPQUAD(dst_ip));
ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", mpc->dev->name, entry);
if(entry == NULL){
......
......@@ -230,7 +230,7 @@ extern void netdev_unregister_sysfs(struct net_device *);
* For efficiency
*/
int netdev_nit;
static int netdev_nit;
/*
* Add a protocol ID to the list. Now that the input handler is
......@@ -1325,9 +1325,12 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
nskb->next = NULL;
rc = dev->hard_start_xmit(nskb, dev);
if (unlikely(rc)) {
nskb->next = skb->next;
skb->next = nskb;
return rc;
}
if (unlikely(netif_queue_stopped(dev) && skb->next))
return NETDEV_TX_BUSY;
} while (skb->next);
skb->destructor = DEV_GSO_CB(skb)->destructor;
......
......@@ -54,6 +54,7 @@ static atomic_t trapped;
sizeof(struct iphdr) + sizeof(struct ethhdr))
static void zap_completion_queue(void);
static void arp_reply(struct sk_buff *skb);
static void queue_process(void *p)
{
......@@ -153,6 +154,22 @@ static void poll_napi(struct netpoll *np)
}
}
static void service_arp_queue(struct netpoll_info *npi)
{
struct sk_buff *skb;
if (unlikely(!npi))
return;
skb = skb_dequeue(&npi->arp_tx);
while (skb != NULL) {
arp_reply(skb);
skb = skb_dequeue(&npi->arp_tx);
}
return;
}
void netpoll_poll(struct netpoll *np)
{
if(!np->dev || !netif_running(np->dev) || !np->dev->poll_controller)
......@@ -163,6 +180,8 @@ void netpoll_poll(struct netpoll *np)
if (np->dev->poll)
poll_napi(np);
service_arp_queue(np->dev->npinfo);
zap_completion_queue();
}
......@@ -279,14 +298,10 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
* network drivers do not expect to be called if the queue is
* stopped.
*/
if (netif_queue_stopped(np->dev)) {
netif_tx_unlock(np->dev);
netpoll_poll(np);
udelay(50);
continue;
}
status = NETDEV_TX_BUSY;
if (!netif_queue_stopped(np->dev))
status = np->dev->hard_start_xmit(skb, np->dev);
netif_tx_unlock(np->dev);
/* success */
......@@ -446,7 +461,9 @@ int __netpoll_rx(struct sk_buff *skb)
int proto, len, ulen;
struct iphdr *iph;
struct udphdr *uh;
struct netpoll *np = skb->dev->npinfo->rx_np;
struct netpoll_info *npi = skb->dev->npinfo;
struct netpoll *np = npi->rx_np;
if (!np)
goto out;
......@@ -456,7 +473,7 @@ int __netpoll_rx(struct sk_buff *skb)
/* check if netpoll clients need ARP */
if (skb->protocol == __constant_htons(ETH_P_ARP) &&
atomic_read(&trapped)) {
arp_reply(skb);
skb_queue_tail(&npi->arp_tx, skb);
return 1;
}
......@@ -651,6 +668,7 @@ int netpoll_setup(struct netpoll *np)
npinfo->poll_owner = -1;
npinfo->tries = MAX_RETRIES;
spin_lock_init(&npinfo->rx_lock);
skb_queue_head_init(&npinfo->arp_tx);
} else
npinfo = ndev->npinfo;
......
......@@ -1739,12 +1739,15 @@ unsigned int skb_find_text(struct sk_buff *skb, unsigned int from,
unsigned int to, struct ts_config *config,
struct ts_state *state)
{
unsigned int ret;
config->get_next_block = skb_ts_get_next_block;
config->finish = skb_ts_finish;
skb_prepare_seq_read(skb, from, to, TS_SKB_CB(state));
return textsearch_find(config, state);
ret = textsearch_find(config, state);
return (ret <= to - from ? ret : UINT_MAX);
}
/**
......
......@@ -2166,7 +2166,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg)
if (!pskb_may_pull(skb, thlen))
goto out;
oldlen = ~htonl(skb->len);
oldlen = (u16)~skb->len;
__skb_pull(skb, thlen);
segs = skb_segment(skb, sg);
......@@ -2174,7 +2174,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg)
goto out;
len = skb_shinfo(skb)->gso_size;
delta = csum_add(oldlen, htonl(thlen + len));
delta = htonl(oldlen + (thlen + len));
skb = segs;
th = skb->h.th;
......@@ -2183,10 +2183,10 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg)
do {
th->fin = th->psh = 0;
if (skb->ip_summed == CHECKSUM_NONE) {
th->check = csum_fold(csum_partial(
skb->h.raw, thlen, csum_add(skb->csum, delta)));
}
th->check = ~csum_fold(th->check + delta);
if (skb->ip_summed != CHECKSUM_HW)
th->check = csum_fold(csum_partial(skb->h.raw, thlen,
skb->csum));
seq += len;
skb = skb->next;
......@@ -2196,11 +2196,11 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg)
th->cwr = 0;
} while (skb->next);
if (skb->ip_summed == CHECKSUM_NONE) {
delta = csum_add(oldlen, htonl(skb->tail - skb->h.raw));
th->check = csum_fold(csum_partial(
skb->h.raw, thlen, csum_add(skb->csum, delta)));
}
delta = htonl(oldlen + (skb->tail - skb->h.raw) + skb->data_len);
th->check = ~csum_fold(th->check + delta);
if (skb->ip_summed != CHECKSUM_HW)
th->check = csum_fold(csum_partial(skb->h.raw, thlen,
skb->csum));
out:
return segs;
......
......@@ -725,15 +725,17 @@ void nr_link_failed(ax25_cb *ax25, int reason)
struct nr_node *nr_node = NULL;
spin_lock_bh(&nr_neigh_list_lock);
nr_neigh_for_each(s, node, &nr_neigh_list)
nr_neigh_for_each(s, node, &nr_neigh_list) {
if (s->ax25 == ax25) {
nr_neigh_hold(s);
nr_neigh = s;
break;
}
}
spin_unlock_bh(&nr_neigh_list_lock);
if (nr_neigh == NULL) return;
if (nr_neigh == NULL)
return;
nr_neigh->ax25 = NULL;
ax25_cb_put(ax25);
......@@ -743,11 +745,13 @@ void nr_link_failed(ax25_cb *ax25, int reason)
return;
}
spin_lock_bh(&nr_node_list_lock);
nr_node_for_each(nr_node, node, &nr_node_list)
nr_node_for_each(nr_node, node, &nr_node_list) {
nr_node_lock(nr_node);
if (nr_node->which < nr_node->count && nr_node->routes[nr_node->which].neighbour == nr_neigh)
if (nr_node->which < nr_node->count &&
nr_node->routes[nr_node->which].neighbour == nr_neigh)
nr_node->which++;
nr_node_unlock(nr_node);
}
spin_unlock_bh(&nr_node_list_lock);
nr_neigh_put(nr_neigh);
}
......
......@@ -49,13 +49,19 @@
#include "name_table.h"
#include "bcast.h"
#define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */
#define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */
#define BCLINK_LOG_BUF_SIZE 0
/*
* Loss rate for incoming broadcast frames; used to test retransmission code.
* Set to N to cause every N'th frame to be discarded; 0 => don't discard any.
*/
#define TIPC_BCAST_LOSS_RATE 0
/**
* struct bcbearer_pair - a pair of bearers used by broadcast link
* @primary: pointer to primary bearer
......@@ -75,7 +81,14 @@ struct bcbearer_pair {
* @bearer: (non-standard) broadcast bearer structure
* @media: (non-standard) broadcast media structure
* @bpairs: array of bearer pairs
* @bpairs_temp: array of bearer pairs used during creation of "bpairs"
* @bpairs_temp: temporary array of bearer pairs used by tipc_bcbearer_sort()
* @remains: temporary node map used by tipc_bcbearer_send()
* @remains_new: temporary node map used tipc_bcbearer_send()
*
* Note: The fields labelled "temporary" are incorporated into the bearer
* to avoid consuming potentially limited stack space through the use of
* large local variables within multicast routines. Concurrent access is
* prevented through use of the spinlock "bc_lock".
*/
struct bcbearer {
......@@ -83,6 +96,8 @@ struct bcbearer {
struct media media;
struct bcbearer_pair bpairs[MAX_BEARERS];
struct bcbearer_pair bpairs_temp[TIPC_MAX_LINK_PRI + 1];
struct node_map remains;
struct node_map remains_new;
};
/**
......@@ -165,21 +180,18 @@ static int bclink_ack_allowed(u32 n)
* @after: sequence number of last packet to *not* retransmit
* @to: sequence number of last packet to retransmit
*
* Called with 'node' locked, bc_lock unlocked
* Called with bc_lock locked
*/
static void bclink_retransmit_pkt(u32 after, u32 to)
{
struct sk_buff *buf;
spin_lock_bh(&bc_lock);
buf = bcl->first_out;
while (buf && less_eq(buf_seqno(buf), after)) {
buf = buf->next;
}
if (buf != NULL)
tipc_link_retransmit(bcl, buf, mod(to - after));
spin_unlock_bh(&bc_lock);
}
/**
......@@ -346,8 +358,10 @@ static void tipc_bclink_peek_nack(u32 dest, u32 sender_tag, u32 gap_after, u32 g
for (; buf; buf = buf->next) {
u32 seqno = buf_seqno(buf);
if (mod(seqno - prev) != 1)
if (mod(seqno - prev) != 1) {
buf = NULL;
break;
}
if (seqno == gap_after)
break;
prev = seqno;
......@@ -400,6 +414,9 @@ int tipc_bclink_send_msg(struct sk_buff *buf)
void tipc_bclink_recv_pkt(struct sk_buff *buf)
{
#if (TIPC_BCAST_LOSS_RATE)
static int rx_count = 0;
#endif
struct tipc_msg *msg = buf_msg(buf);
struct node* node = tipc_node_find(msg_prevnode(msg));
u32 next_in;
......@@ -420,9 +437,13 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
tipc_node_lock(node);
tipc_bclink_acknowledge(node, msg_bcast_ack(msg));
tipc_node_unlock(node);
spin_lock_bh(&bc_lock);
bcl->stats.recv_nacks++;
bcl->owner->next = node; /* remember requestor */
bclink_retransmit_pkt(msg_bcgap_after(msg),
msg_bcgap_to(msg));
bcl->owner->next = NULL;
spin_unlock_bh(&bc_lock);
} else {
tipc_bclink_peek_nack(msg_destnode(msg),
msg_bcast_tag(msg),
......@@ -433,6 +454,14 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
return;
}
#if (TIPC_BCAST_LOSS_RATE)
if (++rx_count == TIPC_BCAST_LOSS_RATE) {
rx_count = 0;
buf_discard(buf);
return;
}
#endif
tipc_node_lock(node);
receive:
deferred = node->bclink.deferred_head;
......@@ -531,12 +560,8 @@ static int tipc_bcbearer_send(struct sk_buff *buf,
{
static int send_count = 0;
struct node_map *remains;
struct node_map *remains_new;
struct node_map *remains_tmp;
int bp_index;
int swap_time;
int err;
/* Prepare buffer for broadcasting (if first time trying to send it) */
......@@ -557,9 +582,7 @@ static int tipc_bcbearer_send(struct sk_buff *buf,
/* Send buffer over bearers until all targets reached */
remains = kmalloc(sizeof(struct node_map), GFP_ATOMIC);
remains_new = kmalloc(sizeof(struct node_map), GFP_ATOMIC);
*remains = tipc_cltr_bcast_nodes;
bcbearer->remains = tipc_cltr_bcast_nodes;
for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) {
struct bearer *p = bcbearer->bpairs[bp_index].primary;
......@@ -568,8 +591,8 @@ static int tipc_bcbearer_send(struct sk_buff *buf,
if (!p)
break; /* no more bearers to try */
tipc_nmap_diff(remains, &p->nodes, remains_new);
if (remains_new->count == remains->count)
tipc_nmap_diff(&bcbearer->remains, &p->nodes, &bcbearer->remains_new);
if (bcbearer->remains_new.count == bcbearer->remains.count)
continue; /* bearer pair doesn't add anything */
if (!p->publ.blocked &&
......@@ -587,27 +610,17 @@ static int tipc_bcbearer_send(struct sk_buff *buf,
bcbearer->bpairs[bp_index].primary = s;
bcbearer->bpairs[bp_index].secondary = p;
update:
if (remains_new->count == 0) {
err = TIPC_OK;
goto out;
}
if (bcbearer->remains_new.count == 0)
return TIPC_OK;
/* swap map */
remains_tmp = remains;
remains = remains_new;
remains_new = remains_tmp;
bcbearer->remains = bcbearer->remains_new;
}
/* Unable to reach all targets */
bcbearer->bearer.publ.blocked = 1;
bcl->stats.bearer_congs++;
err = ~TIPC_OK;
out:
kfree(remains_new);
kfree(remains);
return err;
return ~TIPC_OK;
}
/**
......@@ -765,7 +778,7 @@ int tipc_bclink_init(void)
bclink = kmalloc(sizeof(*bclink), GFP_ATOMIC);
if (!bcbearer || !bclink) {
nomem:
warn("Memory squeeze; Failed to create multicast link\n");
warn("Multicast link creation failed, no memory\n");
kfree(bcbearer);
bcbearer = NULL;
kfree(bclink);
......
......@@ -180,7 +180,7 @@ static inline void tipc_port_list_add(struct port_list *pl_ptr, u32 port)
if (!item->next) {
item->next = kmalloc(sizeof(*item), GFP_ATOMIC);
if (!item->next) {
warn("Memory squeeze: multicast destination port list is incomplete\n");
warn("Incomplete multicast delivery, no memory\n");
return;
}
item->next->next = NULL;
......
......@@ -112,39 +112,42 @@ int tipc_register_media(u32 media_type,
goto exit;
if (!media_name_valid(name)) {
warn("Media registration error: illegal name <%s>\n", name);
warn("Media <%s> rejected, illegal name\n", name);
goto exit;
}
if (!bcast_addr) {
warn("Media registration error: no broadcast address supplied\n");
warn("Media <%s> rejected, no broadcast address\n", name);
goto exit;
}
if ((bearer_priority < TIPC_MIN_LINK_PRI) &&
(bearer_priority > TIPC_MAX_LINK_PRI)) {
warn("Media registration error: priority %u\n", bearer_priority);
warn("Media <%s> rejected, illegal priority (%u)\n", name,
bearer_priority);
goto exit;
}
if ((link_tolerance < TIPC_MIN_LINK_TOL) ||
(link_tolerance > TIPC_MAX_LINK_TOL)) {
warn("Media registration error: tolerance %u\n", link_tolerance);
warn("Media <%s> rejected, illegal tolerance (%u)\n", name,
link_tolerance);
goto exit;
}
media_id = media_count++;
if (media_id >= MAX_MEDIA) {
warn("Attempt to register more than %u media\n", MAX_MEDIA);
warn("Media <%s> rejected, media limit reached (%u)\n", name,
MAX_MEDIA);
media_count--;
goto exit;
}
for (i = 0; i < media_id; i++) {
if (media_list[i].type_id == media_type) {
warn("Attempt to register second media with type %u\n",
warn("Media <%s> rejected, duplicate type (%u)\n", name,
media_type);
media_count--;
goto exit;
}
if (!strcmp(name, media_list[i].name)) {
warn("Attempt to re-register media name <%s>\n", name);
warn("Media <%s> rejected, duplicate name\n", name);
media_count--;
goto exit;
}
......@@ -283,6 +286,9 @@ static struct bearer *bearer_find(const char *name)
struct bearer *b_ptr;
u32 i;
if (tipc_mode != TIPC_NET_MODE)
return NULL;
for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) {
if (b_ptr->active && (!strcmp(b_ptr->publ.name, name)))
return b_ptr;
......@@ -475,26 +481,33 @@ int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority)
u32 i;
int res = -EINVAL;
if (tipc_mode != TIPC_NET_MODE)
if (tipc_mode != TIPC_NET_MODE) {
warn("Bearer <%s> rejected, not supported in standalone mode\n",
name);
return -ENOPROTOOPT;
if (!bearer_name_validate(name, &b_name) ||
!tipc_addr_domain_valid(bcast_scope) ||
!in_scope(bcast_scope, tipc_own_addr))
}
if (!bearer_name_validate(name, &b_name)) {
warn("Bearer <%s> rejected, illegal name\n", name);
return -EINVAL;
}
if (!tipc_addr_domain_valid(bcast_scope) ||
!in_scope(bcast_scope, tipc_own_addr)) {
warn("Bearer <%s> rejected, illegal broadcast scope\n", name);
return -EINVAL;
}
if ((priority < TIPC_MIN_LINK_PRI ||
priority > TIPC_MAX_LINK_PRI) &&
(priority != TIPC_MEDIA_LINK_PRI))
(priority != TIPC_MEDIA_LINK_PRI)) {
warn("Bearer <%s> rejected, illegal priority\n", name);
return -EINVAL;
}
write_lock_bh(&tipc_net_lock);
if (!tipc_bearers)
goto failed;
m_ptr = media_find(b_name.media_name);
if (!m_ptr) {
warn("No media <%s>\n", b_name.media_name);
warn("Bearer <%s> rejected, media <%s> not registered\n", name,
b_name.media_name);
goto failed;
}
......@@ -510,23 +523,24 @@ int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority)
continue;
}
if (!strcmp(name, tipc_bearers[i].publ.name)) {
warn("Bearer <%s> already enabled\n", name);
warn("Bearer <%s> rejected, already enabled\n", name);
goto failed;
}
if ((tipc_bearers[i].priority == priority) &&
(++with_this_prio > 2)) {
if (priority-- == 0) {
warn("Third bearer <%s> with priority %u, unable to lower to %u\n",
name, priority + 1, priority);
warn("Bearer <%s> rejected, duplicate priority\n",
name);
goto failed;
}
warn("Third bearer <%s> with priority %u, lowering to %u\n",
warn("Bearer <%s> priority adjustment required %u->%u\n",
name, priority + 1, priority);
goto restart;
}
}
if (bearer_id >= MAX_BEARERS) {
warn("Attempt to enable more than %d bearers\n", MAX_BEARERS);
warn("Bearer <%s> rejected, bearer limit reached (%u)\n",
name, MAX_BEARERS);
goto failed;
}
......@@ -536,7 +550,7 @@ int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority)
strcpy(b_ptr->publ.name, name);
res = m_ptr->enable_bearer(&b_ptr->publ);
if (res) {
warn("Failed to enable bearer <%s>\n", name);
warn("Bearer <%s> rejected, enable failure (%d)\n", name, -res);
goto failed;
}
......@@ -573,9 +587,6 @@ int tipc_block_bearer(const char *name)
struct link *l_ptr;
struct link *temp_l_ptr;
if (tipc_mode != TIPC_NET_MODE)
return -ENOPROTOOPT;
read_lock_bh(&tipc_net_lock);
b_ptr = bearer_find(name);
if (!b_ptr) {
......@@ -584,6 +595,7 @@ int tipc_block_bearer(const char *name)
return -EINVAL;
}
info("Blocking bearer <%s>\n", name);
spin_lock_bh(&b_ptr->publ.lock);
b_ptr->publ.blocked = 1;
list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
......@@ -595,7 +607,6 @@ int tipc_block_bearer(const char *name)
}
spin_unlock_bh(&b_ptr->publ.lock);
read_unlock_bh(&tipc_net_lock);
info("Blocked bearer <%s>\n", name);
return TIPC_OK;
}
......@@ -611,15 +622,13 @@ static int bearer_disable(const char *name)
struct link *l_ptr;
struct link *temp_l_ptr;
if (tipc_mode != TIPC_NET_MODE)
return -ENOPROTOOPT;
b_ptr = bearer_find(name);
if (!b_ptr) {
warn("Attempt to disable unknown bearer <%s>\n", name);
return -EINVAL;
}
info("Disabling bearer <%s>\n", name);
tipc_disc_stop_link_req(b_ptr->link_req);
spin_lock_bh(&b_ptr->publ.lock);
b_ptr->link_req = NULL;
......@@ -635,7 +644,6 @@ static int bearer_disable(const char *name)
tipc_link_delete(l_ptr);
}
spin_unlock_bh(&b_ptr->publ.lock);
info("Disabled bearer <%s>\n", name);
memset(b_ptr, 0, sizeof(struct bearer));
return TIPC_OK;
}
......
......@@ -60,8 +60,10 @@ struct cluster *tipc_cltr_create(u32 addr)
int alloc;
c_ptr = (struct cluster *)kmalloc(sizeof(*c_ptr), GFP_ATOMIC);
if (c_ptr == NULL)
if (c_ptr == NULL) {
warn("Cluster creation failure, no memory\n");
return NULL;
}
memset(c_ptr, 0, sizeof(*c_ptr));
c_ptr->addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0);
......@@ -70,30 +72,32 @@ struct cluster *tipc_cltr_create(u32 addr)
else
max_nodes = tipc_max_nodes + 1;
alloc = sizeof(void *) * (max_nodes + 1);
c_ptr->nodes = (struct node **)kmalloc(alloc, GFP_ATOMIC);
if (c_ptr->nodes == NULL) {
warn("Cluster creation failure, no memory for node area\n");
kfree(c_ptr);
return NULL;
}
memset(c_ptr->nodes, 0, alloc);
if (in_own_cluster(addr))
tipc_local_nodes = c_ptr->nodes;
c_ptr->highest_slave = LOWEST_SLAVE - 1;
c_ptr->highest_node = 0;
z_ptr = tipc_zone_find(tipc_zone(addr));
if (z_ptr == NULL) {
if (!z_ptr) {
z_ptr = tipc_zone_create(addr);
}
if (z_ptr != NULL) {
tipc_zone_attach_cluster(z_ptr, c_ptr);
c_ptr->owner = z_ptr;
}
else {
if (!z_ptr) {
kfree(c_ptr->nodes);
kfree(c_ptr);
c_ptr = NULL;
return NULL;
}
tipc_zone_attach_cluster(z_ptr, c_ptr);
c_ptr->owner = z_ptr;
return c_ptr;
}
......
......@@ -291,13 +291,22 @@ static struct sk_buff *cfg_set_own_addr(void)
if (!tipc_addr_node_valid(addr))
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (node address)");
if (tipc_own_addr)
if (tipc_mode == TIPC_NET_MODE)
return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
" (cannot change node address once assigned)");
tipc_own_addr = addr;
/*
* Must release all spinlocks before calling start_net() because
* Linux version of TIPC calls eth_media_start() which calls
* register_netdevice_notifier() which may block!
*
* Temporarily releasing the lock should be harmless for non-Linux TIPC,
* but Linux version of eth_media_start() should really be reworked
* so that it can be called with spinlocks held.
*/
spin_unlock_bh(&config_lock);
tipc_core_stop_net();
tipc_own_addr = addr;
tipc_core_start_net();
spin_lock_bh(&config_lock);
return tipc_cfg_reply_none();
......@@ -350,50 +359,21 @@ static struct sk_buff *cfg_set_max_subscriptions(void)
static struct sk_buff *cfg_set_max_ports(void)
{
int orig_mode;
u32 value;
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
value = *(u32 *)TLV_DATA(req_tlv_area);
value = ntohl(value);
if (value == tipc_max_ports)
return tipc_cfg_reply_none();
if (value != delimit(value, 127, 65535))
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (max ports must be 127-65535)");
if (value == tipc_max_ports)
return tipc_cfg_reply_none();
if (atomic_read(&tipc_user_count) > 2)
if (tipc_mode != TIPC_NOT_RUNNING)
return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
" (cannot change max ports while TIPC users exist)");
spin_unlock_bh(&config_lock);
orig_mode = tipc_get_mode();
if (orig_mode == TIPC_NET_MODE)
tipc_core_stop_net();
tipc_core_stop();
" (cannot change max ports while TIPC is active)");
tipc_max_ports = value;
tipc_core_start();
if (orig_mode == TIPC_NET_MODE)
tipc_core_start_net();
spin_lock_bh(&config_lock);
return tipc_cfg_reply_none();
}
static struct sk_buff *set_net_max(int value, int *parameter)
{
int orig_mode;
if (value != *parameter) {
orig_mode = tipc_get_mode();
if (orig_mode == TIPC_NET_MODE)
tipc_core_stop_net();
*parameter = value;
if (orig_mode == TIPC_NET_MODE)
tipc_core_start_net();
}
return tipc_cfg_reply_none();
}
......@@ -405,10 +385,16 @@ static struct sk_buff *cfg_set_max_zones(void)
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
value = *(u32 *)TLV_DATA(req_tlv_area);
value = ntohl(value);
if (value == tipc_max_zones)
return tipc_cfg_reply_none();
if (value != delimit(value, 1, 255))
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (max zones must be 1-255)");
return set_net_max(value, &tipc_max_zones);
if (tipc_mode == TIPC_NET_MODE)
return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
" (cannot change max zones once TIPC has joined a network)");
tipc_max_zones = value;
return tipc_cfg_reply_none();
}
static struct sk_buff *cfg_set_max_clusters(void)
......@@ -419,8 +405,8 @@ static struct sk_buff *cfg_set_max_clusters(void)
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
value = *(u32 *)TLV_DATA(req_tlv_area);
value = ntohl(value);
if (value != 1)
return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
if (value != delimit(value, 1, 1))
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (max clusters fixed at 1)");
return tipc_cfg_reply_none();
}
......@@ -433,10 +419,16 @@ static struct sk_buff *cfg_set_max_nodes(void)
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
value = *(u32 *)TLV_DATA(req_tlv_area);
value = ntohl(value);
if (value == tipc_max_nodes)
return tipc_cfg_reply_none();
if (value != delimit(value, 8, 2047))
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (max nodes must be 8-2047)");
return set_net_max(value, &tipc_max_nodes);
if (tipc_mode == TIPC_NET_MODE)
return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
" (cannot change max nodes once TIPC has joined a network)");
tipc_max_nodes = value;
return tipc_cfg_reply_none();
}
static struct sk_buff *cfg_set_max_slaves(void)
......@@ -461,15 +453,16 @@ static struct sk_buff *cfg_set_netid(void)
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
value = *(u32 *)TLV_DATA(req_tlv_area);
value = ntohl(value);
if (value == tipc_net_id)
return tipc_cfg_reply_none();
if (value != delimit(value, 1, 9999))
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (network id must be 1-9999)");
if (tipc_own_addr)
if (tipc_mode == TIPC_NET_MODE)
return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
" (cannot change network id once part of network)");
return set_net_max(value, &tipc_net_id);
" (cannot change network id once TIPC has joined a network)");
tipc_net_id = value;
return tipc_cfg_reply_none();
}
struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area,
......@@ -649,7 +642,7 @@ static void cfg_named_msg_event(void *userdata,
if ((size < sizeof(*req_hdr)) ||
(size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) ||
(ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) {
warn("discarded invalid configuration message\n");
warn("Invalid configuration message discarded\n");
return;
}
......
......@@ -2,7 +2,7 @@
* net/tipc/core.c: TIPC module code
*
* Copyright (c) 2003-2006, Ericsson AB
* Copyright (c) 2005, Wind River Systems
* Copyright (c) 2005-2006, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -57,7 +57,7 @@ void tipc_socket_stop(void);
int tipc_netlink_start(void);
void tipc_netlink_stop(void);
#define MOD_NAME "tipc_start: "
#define TIPC_MOD_VER "1.6.1"
#ifndef CONFIG_TIPC_ZONES
#define CONFIG_TIPC_ZONES 3
......@@ -198,7 +198,7 @@ static int __init tipc_init(void)
tipc_max_publications = 10000;
tipc_max_subscriptions = 2000;
tipc_max_ports = delimit(CONFIG_TIPC_PORTS, 127, 65536);
tipc_max_zones = delimit(CONFIG_TIPC_ZONES, 1, 511);
tipc_max_zones = delimit(CONFIG_TIPC_ZONES, 1, 255);
tipc_max_clusters = delimit(CONFIG_TIPC_CLUSTERS, 1, 1);
tipc_max_nodes = delimit(CONFIG_TIPC_NODES, 8, 2047);
tipc_max_slaves = delimit(CONFIG_TIPC_SLAVE_NODES, 0, 2047);
......@@ -224,6 +224,7 @@ module_exit(tipc_exit);
MODULE_DESCRIPTION("TIPC: Transparent Inter Process Communication");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(TIPC_MOD_VER);
/* Native TIPC API for kernel-space applications (see tipc.h) */
......
......@@ -2,7 +2,7 @@
* net/tipc/core.h: Include file for TIPC global declarations
*
* Copyright (c) 2005-2006, Ericsson AB
* Copyright (c) 2005, Wind River Systems
* Copyright (c) 2005-2006, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -111,10 +111,6 @@ void tipc_dump(struct print_buf*,const char *fmt, ...);
#else
#ifndef DBG_OUTPUT
#define DBG_OUTPUT NULL
#endif
/*
* TIPC debug support not included:
* - system messages are printed to system console
......@@ -129,6 +125,19 @@ void tipc_dump(struct print_buf*,const char *fmt, ...);
#define msg_dbg(msg,txt) do {} while (0)
#define dump(fmt,arg...) do {} while (0)
/*
* TIPC_OUTPUT is defined to be the system console, while DBG_OUTPUT is
* the null print buffer. Thes ensures that any system or debug messages
* that are generated without using the above macros are handled correctly.
*/
#undef TIPC_OUTPUT
#define TIPC_OUTPUT TIPC_CONS
#undef DBG_OUTPUT
#define DBG_OUTPUT NULL
#endif
......@@ -309,7 +318,7 @@ static inline struct sk_buff *buf_acquire(u32 size)
* buf_discard - frees a TIPC message buffer
* @skb: message buffer
*
* Frees a new buffer. If passed NULL, just returns.
* Frees a message buffer. If passed NULL, just returns.
*/
static inline void buf_discard(struct sk_buff *skb)
......
......@@ -2,7 +2,7 @@
* net/tipc/discover.c
*
* Copyright (c) 2003-2006, Ericsson AB
* Copyright (c) 2005, Wind River Systems
* Copyright (c) 2005-2006, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -176,7 +176,6 @@ void tipc_disc_recv_msg(struct sk_buff *buf)
n_ptr = tipc_node_create(orig);
}
if (n_ptr == NULL) {
warn("Memory squeeze; Failed to create node\n");
return;
}
spin_lock_bh(&n_ptr->lock);
......@@ -191,10 +190,8 @@ void tipc_disc_recv_msg(struct sk_buff *buf)
}
addr = &link->media_addr;
if (memcmp(addr, &media_addr, sizeof(*addr))) {
char addr_string[16];
warn("New bearer address for %s\n",
addr_string_fill(addr_string, orig));
warn("Resetting link <%s>, peer interface address changed\n",
link->name);
memcpy(addr, &media_addr, sizeof(*addr));
tipc_link_reset(link);
}
......@@ -270,8 +267,8 @@ static void disc_timeout(struct link_req *req)
/* leave timer interval "as is" if already at a "normal" rate */
} else {
req->timer_intv *= 2;
if (req->timer_intv > TIPC_LINK_REQ_SLOW)
req->timer_intv = TIPC_LINK_REQ_SLOW;
if (req->timer_intv > TIPC_LINK_REQ_FAST)
req->timer_intv = TIPC_LINK_REQ_FAST;
if ((req->timer_intv == TIPC_LINK_REQ_FAST) &&
(req->bearer->nodes.count))
req->timer_intv = TIPC_LINK_REQ_SLOW;
......
......@@ -2,7 +2,7 @@
* net/tipc/eth_media.c: Ethernet bearer support for TIPC
*
* Copyright (c) 2001-2006, Ericsson AB
* Copyright (c) 2005, Wind River Systems
* Copyright (c) 2005-2006, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -98,17 +98,19 @@ static int recv_msg(struct sk_buff *buf, struct net_device *dev,
u32 size;
if (likely(eb_ptr->bearer)) {
if (likely(!dev->promiscuity) ||
!memcmp(buf->mac.raw,dev->dev_addr,ETH_ALEN) ||
!memcmp(buf->mac.raw,dev->broadcast,ETH_ALEN)) {
size = msg_size((struct tipc_msg *)buf->data);
skb_trim(buf, size);
if (likely(buf->len == size)) {
buf->next = NULL;
tipc_recv_msg(buf, eb_ptr->bearer);
} else {
kfree_skb(buf);
return TIPC_OK;
}
} else {
kfree_skb(buf);
}
}
kfree_skb(buf);
return TIPC_OK;
}
......@@ -125,8 +127,7 @@ static int enable_bearer(struct tipc_bearer *tb_ptr)
/* Find device with specified name */
while (dev && dev->name &&
(memcmp(dev->name, driver_name, strlen(dev->name)))) {
while (dev && dev->name && strncmp(dev->name, driver_name, IFNAMSIZ)) {
dev = dev->next;
}
if (!dev)
......@@ -252,7 +253,9 @@ int tipc_eth_media_start(void)
if (eth_started)
return -EINVAL;
memset(&bcast_addr, 0xff, sizeof(bcast_addr));
bcast_addr.type = htonl(TIPC_MEDIA_TYPE_ETH);
memset(&bcast_addr.dev_addr, 0xff, ETH_ALEN);
memset(eth_bearers, 0, sizeof(eth_bearers));
res = tipc_register_media(TIPC_MEDIA_TYPE_ETH, "eth",
......
This diff is collapsed.
......@@ -127,7 +127,7 @@ void tipc_named_publish(struct publication *publ)
buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0);
if (!buf) {
warn("Memory squeeze; failed to distribute publication\n");
warn("Publication distribution failure\n");
return;
}
......@@ -151,7 +151,7 @@ void tipc_named_withdraw(struct publication *publ)
buf = named_prepare_buf(WITHDRAWAL, ITEM_SIZE, 0);
if (!buf) {
warn("Memory squeeze; failed to distribute withdrawal\n");
warn("Withdrawl distribution failure\n");
return;
}
......@@ -174,7 +174,6 @@ void tipc_named_node_up(unsigned long node)
u32 rest;
u32 max_item_buf;
assert(in_own_cluster(node));
read_lock_bh(&tipc_nametbl_lock);
max_item_buf = TIPC_MAX_USER_MSG_SIZE / ITEM_SIZE;
max_item_buf *= ITEM_SIZE;
......@@ -185,8 +184,8 @@ void tipc_named_node_up(unsigned long node)
left = (rest <= max_item_buf) ? rest : max_item_buf;
rest -= left;
buf = named_prepare_buf(PUBLICATION, left, node);
if (buf == NULL) {
warn("Memory Squeeze; could not send publication\n");
if (!buf) {
warn("Bulk publication distribution failure\n");
goto exit;
}
item = (struct distr_item *)msg_data(buf_msg(buf));
......@@ -221,15 +220,24 @@ void tipc_named_node_up(unsigned long node)
static void node_is_down(struct publication *publ)
{
struct publication *p;
write_lock_bh(&tipc_nametbl_lock);
dbg("node_is_down: withdrawing %u, %u, %u\n",
publ->type, publ->lower, publ->upper);
publ->key += 1222345;
p = tipc_nametbl_remove_publ(publ->type, publ->lower,
publ->node, publ->ref, publ->key);
assert(p == publ);
write_unlock_bh(&tipc_nametbl_lock);
kfree(publ);
if (p != publ) {
err("Unable to remove publication from failed node\n"
"(type=%u, lower=%u, node=0x%x, ref=%u, key=%u)\n",
publ->type, publ->lower, publ->node, publ->ref, publ->key);
}
if (p) {
kfree(p);
}
}
/**
......@@ -275,9 +283,15 @@ void tipc_named_recv(struct sk_buff *buf)
if (publ) {
tipc_nodesub_unsubscribe(&publ->subscr);
kfree(publ);
} else {
err("Unable to remove publication by node 0x%x\n"
"(type=%u, lower=%u, ref=%u, key=%u)\n",
msg_orignode(msg),
ntohl(item->type), ntohl(item->lower),
ntohl(item->ref), ntohl(item->key));
}
} else {
warn("tipc_named_recv: unknown msg\n");
warn("Unrecognized name table message received\n");
}
item++;
}
......
This diff is collapsed.
......@@ -61,16 +61,24 @@ struct node *tipc_node_create(u32 addr)
struct node **curr_node;
n_ptr = kmalloc(sizeof(*n_ptr),GFP_ATOMIC);
if (n_ptr != NULL) {
if (!n_ptr) {
warn("Node creation failed, no memory\n");
return NULL;
}
c_ptr = tipc_cltr_find(addr);
if (!c_ptr) {
c_ptr = tipc_cltr_create(addr);
}
if (!c_ptr) {
kfree(n_ptr);
return NULL;
}
memset(n_ptr, 0, sizeof(*n_ptr));
n_ptr->addr = addr;
n_ptr->lock = SPIN_LOCK_UNLOCKED;
INIT_LIST_HEAD(&n_ptr->nsub);
c_ptr = tipc_cltr_find(addr);
if (c_ptr == NULL)
c_ptr = tipc_cltr_create(addr);
if (c_ptr != NULL) {
n_ptr->owner = c_ptr;
tipc_cltr_attach_node(c_ptr, n_ptr);
n_ptr->last_router = -1;
......@@ -84,11 +92,6 @@ struct node *tipc_node_create(u32 addr)
}
}
(*curr_node) = n_ptr;
} else {
kfree(n_ptr);
n_ptr = NULL;
}
}
return n_ptr;
}
......@@ -122,6 +125,8 @@ void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr)
{
struct link **active = &n_ptr->active_links[0];
n_ptr->working_links++;
info("Established link <%s> on network plane %c\n",
l_ptr->name, l_ptr->b_ptr->net_plane);
......@@ -132,7 +137,7 @@ void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr)
return;
}
if (l_ptr->priority < active[0]->priority) {
info("Link is standby\n");
info("New link <%s> becomes standby\n", l_ptr->name);
return;
}
tipc_link_send_duplicate(active[0], l_ptr);
......@@ -140,8 +145,9 @@ void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr)
active[0] = l_ptr;
return;
}
info("Link <%s> on network plane %c becomes standby\n",
active[0]->name, active[0]->b_ptr->net_plane);
info("Old link <%s> becomes standby\n", active[0]->name);
if (active[1] != active[0])
info("Old link <%s> becomes standby\n", active[1]->name);
active[0] = active[1] = l_ptr;
}
......@@ -181,6 +187,8 @@ void tipc_node_link_down(struct node *n_ptr, struct link *l_ptr)
{
struct link **active;
n_ptr->working_links--;
if (!tipc_link_is_active(l_ptr)) {
info("Lost standby link <%s> on network plane %c\n",
l_ptr->name, l_ptr->b_ptr->net_plane);
......@@ -210,8 +218,7 @@ int tipc_node_has_active_links(struct node *n_ptr)
int tipc_node_has_redundant_links(struct node *n_ptr)
{
return (tipc_node_has_active_links(n_ptr) &&
(n_ptr->active_links[0] != n_ptr->active_links[1]));
return (n_ptr->working_links > 1);
}
static int tipc_node_has_active_routes(struct node *n_ptr)
......@@ -234,7 +241,6 @@ struct node *tipc_node_attach_link(struct link *l_ptr)
u32 bearer_id = l_ptr->b_ptr->identity;
char addr_string[16];
assert(bearer_id < MAX_BEARERS);
if (n_ptr->link_cnt >= 2) {
char addr_string[16];
......@@ -249,7 +255,7 @@ struct node *tipc_node_attach_link(struct link *l_ptr)
n_ptr->link_cnt++;
return n_ptr;
}
err("Attempt to establish second link on <%s> to <%s> \n",
err("Attempt to establish second link on <%s> to %s \n",
l_ptr->b_ptr->publ.name,
addr_string_fill(addr_string, l_ptr->addr));
}
......@@ -314,7 +320,7 @@ static void node_established_contact(struct node *n_ptr)
struct cluster *c_ptr;
dbg("node_established_contact:-> %x\n", n_ptr->addr);
if (!tipc_node_has_active_routes(n_ptr)) {
if (!tipc_node_has_active_routes(n_ptr) && in_own_cluster(n_ptr->addr)) {
tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr);
}
......
......@@ -51,6 +51,7 @@
* @nsub: list of "node down" subscriptions monitoring node
* @active_links: pointers to active links to node
* @links: pointers to all links to node
* @working_links: number of working links to node (both active and standby)
* @link_cnt: number of links to node
* @permit_changeover: non-zero if node has redundant links to this system
* @routers: bitmap (used for multicluster communication)
......@@ -76,6 +77,7 @@ struct node {
struct link *active_links[2];
struct link *links[MAX_BEARERS];
int link_cnt;
int working_links;
int permit_changeover;
u32 routers[512/32];
int last_router;
......
......@@ -47,18 +47,19 @@
void tipc_nodesub_subscribe(struct node_subscr *node_sub, u32 addr,
void *usr_handle, net_ev_handler handle_down)
{
if (addr == tipc_own_addr) {
node_sub->node = NULL;
if (addr == tipc_own_addr)
return;
if (!tipc_addr_node_valid(addr)) {
warn("node_subscr with illegal %x\n", addr);
return;
}
node_sub->node = tipc_node_find(addr);
if (!node_sub->node) {
warn("Node subscription rejected, unknown node 0x%x\n", addr);
return;
}
node_sub->handle_node_down = handle_down;
node_sub->usr_handle = usr_handle;
node_sub->node = tipc_node_find(addr);
assert(node_sub->node);
tipc_node_lock(node_sub->node);
list_add_tail(&node_sub->nodesub_list, &node_sub->node->nsub);
tipc_node_unlock(node_sub->node);
......
......@@ -168,7 +168,6 @@ void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp)
struct port_list *item = dp;
int cnt = 0;
assert(buf);
msg = buf_msg(buf);
/* Create destination port list, if one wasn't supplied */
......@@ -196,7 +195,7 @@ void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp)
struct sk_buff *b = skb_clone(buf, GFP_ATOMIC);
if (b == NULL) {
warn("Buffer allocation failure\n");
warn("Unable to deliver multicast message(s)\n");
msg_dbg(msg, "LOST:");
goto exit;
}
......@@ -228,14 +227,14 @@ u32 tipc_createport_raw(void *usr_handle,
u32 ref;
p_ptr = kmalloc(sizeof(*p_ptr), GFP_ATOMIC);
if (p_ptr == NULL) {
warn("Memory squeeze; failed to create port\n");
if (!p_ptr) {
warn("Port creation failed, no memory\n");
return 0;
}
memset(p_ptr, 0, sizeof(*p_ptr));
ref = tipc_ref_acquire(p_ptr, &p_ptr->publ.lock);
if (!ref) {
warn("Reference Table Exhausted\n");
warn("Port creation failed, reference table exhausted\n");
kfree(p_ptr);
return 0;
}
......@@ -810,18 +809,20 @@ static void port_dispatcher_sigh(void *dummy)
void *usr_handle;
int connected;
int published;
u32 message_type;
struct sk_buff *next = buf->next;
struct tipc_msg *msg = buf_msg(buf);
u32 dref = msg_destport(msg);
message_type = msg_type(msg);
if (message_type > TIPC_DIRECT_MSG)
goto reject; /* Unsupported message type */
p_ptr = tipc_port_lock(dref);
if (!p_ptr) {
/* Port deleted while msg in queue */
tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
buf = next;
continue;
}
if (!p_ptr)
goto reject; /* Port deleted while msg in queue */
orig.ref = msg_origport(msg);
orig.node = msg_orignode(msg);
up_ptr = p_ptr->user_port;
......@@ -832,7 +833,7 @@ static void port_dispatcher_sigh(void *dummy)
if (unlikely(msg_errcode(msg)))
goto err;
switch (msg_type(msg)) {
switch (message_type) {
case TIPC_CONN_MSG:{
tipc_conn_msg_event cb = up_ptr->conn_msg_cb;
......@@ -874,6 +875,7 @@ static void port_dispatcher_sigh(void *dummy)
&orig);
break;
}
case TIPC_MCAST_MSG:
case TIPC_NAMED_MSG:{
tipc_named_msg_event cb = up_ptr->named_msg_cb;
......@@ -886,7 +888,8 @@ static void port_dispatcher_sigh(void *dummy)
goto reject;
dseq.type = msg_nametype(msg);
dseq.lower = msg_nameinst(msg);
dseq.upper = dseq.lower;
dseq.upper = (message_type == TIPC_NAMED_MSG)
? dseq.lower : msg_nameupper(msg);
skb_pull(buf, msg_hdr_sz(msg));
cb(usr_handle, dref, &buf, msg_data(msg),
msg_data_sz(msg), msg_importance(msg),
......@@ -899,7 +902,7 @@ static void port_dispatcher_sigh(void *dummy)
buf = next;
continue;
err:
switch (msg_type(msg)) {
switch (message_type) {
case TIPC_CONN_MSG:{
tipc_conn_shutdown_event cb =
......@@ -931,6 +934,7 @@ static void port_dispatcher_sigh(void *dummy)
msg_data_sz(msg), msg_errcode(msg), &orig);
break;
}
case TIPC_MCAST_MSG:
case TIPC_NAMED_MSG:{
tipc_named_msg_err_event cb =
up_ptr->named_err_cb;
......@@ -940,7 +944,8 @@ static void port_dispatcher_sigh(void *dummy)
break;
dseq.type = msg_nametype(msg);
dseq.lower = msg_nameinst(msg);
dseq.upper = dseq.lower;
dseq.upper = (message_type == TIPC_NAMED_MSG)
? dseq.lower : msg_nameupper(msg);
skb_pull(buf, msg_hdr_sz(msg));
cb(usr_handle, dref, &buf, msg_data(msg),
msg_data_sz(msg), msg_errcode(msg), &dseq);
......@@ -1054,7 +1059,8 @@ int tipc_createport(u32 user_ref,
u32 ref;
up_ptr = (struct user_port *)kmalloc(sizeof(*up_ptr), GFP_ATOMIC);
if (up_ptr == NULL) {
if (!up_ptr) {
warn("Port creation failed, no memory\n");
return -ENOMEM;
}
ref = tipc_createport_raw(NULL, port_dispatcher, port_wakeup, importance);
......@@ -1165,8 +1171,6 @@ int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
p_ptr = tipc_port_lock(ref);
if (!p_ptr)
return -EINVAL;
if (!p_ptr->publ.published)
goto exit;
if (!seq) {
list_for_each_entry_safe(publ, tpubl,
&p_ptr->publications, pport_list) {
......@@ -1193,7 +1197,6 @@ int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
}
if (list_empty(&p_ptr->publications))
p_ptr->publ.published = 0;
exit:
tipc_port_unlock(p_ptr);
return res;
}
......
......@@ -127,7 +127,14 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock)
u32 next_plus_upper;
u32 reference = 0;
assert(tipc_ref_table.entries && object);
if (!object) {
err("Attempt to acquire reference to non-existent object\n");
return 0;
}
if (!tipc_ref_table.entries) {
err("Reference table not found during acquisition attempt\n");
return 0;
}
write_lock_bh(&ref_table_lock);
if (tipc_ref_table.first_free) {
......@@ -162,15 +169,28 @@ void tipc_ref_discard(u32 ref)
u32 index;
u32 index_mask;
assert(tipc_ref_table.entries);
assert(ref != 0);
if (!ref) {
err("Attempt to discard reference 0\n");
return;
}
if (!tipc_ref_table.entries) {
err("Reference table not found during discard attempt\n");
return;
}
write_lock_bh(&ref_table_lock);
index_mask = tipc_ref_table.index_mask;
index = ref & index_mask;
entry = &(tipc_ref_table.entries[index]);
assert(entry->object != 0);
assert(entry->data.reference == ref);
if (!entry->object) {
err("Attempt to discard reference to non-existent object\n");
goto exit;
}
if (entry->data.reference != ref) {
err("Attempt to discard non-existent reference\n");
goto exit;
}
/* mark entry as unused */
entry->object = NULL;
......@@ -184,6 +204,7 @@ void tipc_ref_discard(u32 ref)
/* increment upper bits of entry to invalidate subsequent references */
entry->data.next_plus_upper = (ref & ~index_mask) + (index_mask + 1);
exit:
write_unlock_bh(&ref_table_lock);
}
......@@ -169,12 +169,6 @@ static int tipc_create(struct socket *sock, int protocol)
struct sock *sk;
u32 ref;
if ((sock->type != SOCK_STREAM) &&
(sock->type != SOCK_SEQPACKET) &&
(sock->type != SOCK_DGRAM) &&
(sock->type != SOCK_RDM))
return -EPROTOTYPE;
if (unlikely(protocol != 0))
return -EPROTONOSUPPORT;
......@@ -199,6 +193,9 @@ static int tipc_create(struct socket *sock, int protocol)
sock->ops = &msg_ops;
sock->state = SS_READY;
break;
default:
tipc_deleteport(ref);
return -EPROTOTYPE;
}
sk = sk_alloc(AF_TIPC, GFP_KERNEL, &tipc_proto, 1);
......@@ -426,7 +423,7 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m)
if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr)))
return -EFAULT;
if ((ntohs(hdr.tcm_type) & 0xC000) & (!capable(CAP_NET_ADMIN)))
if ((ntohs(hdr.tcm_type) & 0xC000) && (!capable(CAP_NET_ADMIN)))
return -EACCES;
return 0;
......@@ -437,7 +434,7 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m)
* @iocb: (unused)
* @sock: socket structure
* @m: message to send
* @total_len: (unused)
* @total_len: length of message
*
* Message must have an destination specified explicitly.
* Used for SOCK_RDM and SOCK_DGRAM messages,
......@@ -458,7 +455,8 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,
if (unlikely(!dest))
return -EDESTADDRREQ;
if (unlikely(dest->family != AF_TIPC))
if (unlikely((m->msg_namelen < sizeof(*dest)) ||
(dest->family != AF_TIPC)))
return -EINVAL;
needs_conn = (sock->state != SS_READY);
......@@ -470,6 +468,10 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,
if ((tsock->p->published) ||
((sock->type == SOCK_STREAM) && (total_len != 0)))
return -EOPNOTSUPP;
if (dest->addrtype == TIPC_ADDR_NAME) {
tsock->p->conn_type = dest->addr.name.name.type;
tsock->p->conn_instance = dest->addr.name.name.instance;
}
}
if (down_interruptible(&tsock->sem))
......@@ -538,7 +540,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,
* @iocb: (unused)
* @sock: socket structure
* @m: message to send
* @total_len: (unused)
* @total_len: length of message
*
* Used for SOCK_SEQPACKET messages and SOCK_STREAM data.
*
......@@ -561,6 +563,7 @@ static int send_packet(struct kiocb *iocb, struct socket *sock,
return -ERESTARTSYS;
}
do {
if (unlikely(sock->state != SS_CONNECTED)) {
if (sock->state == SS_DISCONNECTING)
res = -EPIPE;
......@@ -569,7 +572,6 @@ static int send_packet(struct kiocb *iocb, struct socket *sock,
goto exit;
}
do {
res = tipc_send(tsock->p->ref, m->msg_iovlen, m->msg_iov);
if (likely(res != -ELINKCONG)) {
exit:
......@@ -597,7 +599,8 @@ static int send_packet(struct kiocb *iocb, struct socket *sock,
*
* Used for SOCK_STREAM data.
*
* Returns the number of bytes sent on success, or errno otherwise
* Returns the number of bytes sent on success (or partial success),
* or errno if no data sent
*/
......@@ -611,6 +614,7 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
char __user *curr_start;
int curr_left;
int bytes_to_send;
int bytes_sent;
int res;
if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE))
......@@ -633,11 +637,11 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
* of small iovec entries into send_packet().
*/
my_msg = *m;
curr_iov = my_msg.msg_iov;
curr_iovlen = my_msg.msg_iovlen;
curr_iov = m->msg_iov;
curr_iovlen = m->msg_iovlen;
my_msg.msg_iov = &my_iov;
my_msg.msg_iovlen = 1;
bytes_sent = 0;
while (curr_iovlen--) {
curr_start = curr_iov->iov_base;
......@@ -648,16 +652,18 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
? curr_left : TIPC_MAX_USER_MSG_SIZE;
my_iov.iov_base = curr_start;
my_iov.iov_len = bytes_to_send;
if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0)
return res;
if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) {
return bytes_sent ? bytes_sent : res;
}
curr_left -= bytes_to_send;
curr_start += bytes_to_send;
bytes_sent += bytes_to_send;
}
curr_iov++;
}
return total_len;
return bytes_sent;
}
/**
......@@ -727,6 +733,7 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
u32 anc_data[3];
u32 err;
u32 dest_type;
int has_name;
int res;
if (likely(m->msg_controllen == 0))
......@@ -738,10 +745,10 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
if (unlikely(err)) {
anc_data[0] = err;
anc_data[1] = msg_data_sz(msg);
if ((res = put_cmsg(m, SOL_SOCKET, TIPC_ERRINFO, 8, anc_data)))
if ((res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data)))
return res;
if (anc_data[1] &&
(res = put_cmsg(m, SOL_SOCKET, TIPC_RETDATA, anc_data[1],
(res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1],
msg_data(msg))))
return res;
}
......@@ -751,25 +758,28 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG;
switch (dest_type) {
case TIPC_NAMED_MSG:
has_name = 1;
anc_data[0] = msg_nametype(msg);
anc_data[1] = msg_namelower(msg);
anc_data[2] = msg_namelower(msg);
break;
case TIPC_MCAST_MSG:
has_name = 1;
anc_data[0] = msg_nametype(msg);
anc_data[1] = msg_namelower(msg);
anc_data[2] = msg_nameupper(msg);
break;
case TIPC_CONN_MSG:
has_name = (tport->conn_type != 0);
anc_data[0] = tport->conn_type;
anc_data[1] = tport->conn_instance;
anc_data[2] = tport->conn_instance;
break;
default:
anc_data[0] = 0;
has_name = 0;
}
if (anc_data[0] &&
(res = put_cmsg(m, SOL_SOCKET, TIPC_DESTNAME, 12, anc_data)))
if (has_name &&
(res = put_cmsg(m, SOL_TIPC, TIPC_DESTNAME, 12, anc_data)))
return res;
return 0;
......@@ -960,7 +970,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
restart:
if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) &&
(flags & MSG_DONTWAIT))) {
res = (sz_copied == 0) ? -EWOULDBLOCK : 0;
res = -EWOULDBLOCK;
goto exit;
}
......@@ -1051,7 +1061,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
exit:
up(&tsock->sem);
return res ? res : sz_copied;
return sz_copied ? sz_copied : res;
}
/**
......@@ -1236,7 +1246,8 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
if (sock->state == SS_READY)
return -EOPNOTSUPP;
/* MOVE THE REST OF THIS ERROR CHECKING TO send_msg()? */
/* Issue Posix-compliant error code if socket is in the wrong state */
if (sock->state == SS_LISTENING)
return -EOPNOTSUPP;
if (sock->state == SS_CONNECTING)
......@@ -1244,13 +1255,20 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
if (sock->state != SS_UNCONNECTED)
return -EISCONN;
if ((dst->family != AF_TIPC) ||
((dst->addrtype != TIPC_ADDR_NAME) && (dst->addrtype != TIPC_ADDR_ID)))
/*
* Reject connection attempt using multicast address
*
* Note: send_msg() validates the rest of the address fields,
* so there's no need to do it here
*/
if (dst->addrtype == TIPC_ADDR_MCAST)
return -EINVAL;
/* Send a 'SYN-' to destination */
m.msg_name = dest;
m.msg_namelen = destlen;
if ((res = send_msg(NULL, sock, &m, 0)) < 0) {
sock->state = SS_DISCONNECTING;
return res;
......@@ -1269,10 +1287,6 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
msg = buf_msg(buf);
res = auto_connect(sock, tsock, msg);
if (!res) {
if (dst->addrtype == TIPC_ADDR_NAME) {
tsock->p->conn_type = dst->addr.name.name.type;
tsock->p->conn_instance = dst->addr.name.name.instance;
}
if (!msg_data_sz(msg))
advance_queue(tsock);
}
......@@ -1386,7 +1400,7 @@ static int accept(struct socket *sock, struct socket *newsock, int flags)
/**
* shutdown - shutdown socket connection
* @sock: socket structure
* @how: direction to close (always treated as read + write)
* @how: direction to close (unused; always treated as read + write)
*
* Terminates connection (if necessary), then purges socket's receive queue.
*
......@@ -1469,7 +1483,8 @@ static int shutdown(struct socket *sock, int how)
* Returns 0 on success, errno otherwise
*/
static int setsockopt(struct socket *sock, int lvl, int opt, char *ov, int ol)
static int setsockopt(struct socket *sock,
int lvl, int opt, char __user *ov, int ol)
{
struct tipc_sock *tsock = tipc_sk(sock->sk);
u32 value;
......@@ -1525,7 +1540,8 @@ static int setsockopt(struct socket *sock, int lvl, int opt, char *ov, int ol)
* Returns 0 on success, errno otherwise
*/
static int getsockopt(struct socket *sock, int lvl, int opt, char *ov, int *ol)
static int getsockopt(struct socket *sock,
int lvl, int opt, char __user *ov, int *ol)
{
struct tipc_sock *tsock = tipc_sk(sock->sk);
int len;
......
......@@ -266,7 +266,8 @@ static void subscr_subscribe(struct tipc_subscr *s,
/* Refuse subscription if global limit exceeded */
if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) {
warn("Failed: max %u subscriptions\n", tipc_max_subscriptions);
warn("Subscription rejected, subscription limit reached (%u)\n",
tipc_max_subscriptions);
subscr_terminate(subscriber);
return;
}
......@@ -274,8 +275,8 @@ static void subscr_subscribe(struct tipc_subscr *s,
/* Allocate subscription object */
sub = kmalloc(sizeof(*sub), GFP_ATOMIC);
if (sub == NULL) {
warn("Memory squeeze; ignoring subscription\n");
if (!sub) {
warn("Subscription rejected, no memory\n");
subscr_terminate(subscriber);
return;
}
......@@ -298,8 +299,7 @@ static void subscr_subscribe(struct tipc_subscr *s,
if ((((sub->filter != TIPC_SUB_PORTS)
&& (sub->filter != TIPC_SUB_SERVICE)))
|| (sub->seq.lower > sub->seq.upper)) {
warn("Rejecting illegal subscription %u,%u,%u\n",
sub->seq.type, sub->seq.lower, sub->seq.upper);
warn("Subscription rejected, illegal request\n");
kfree(sub);
subscr_terminate(subscriber);
return;
......@@ -387,7 +387,7 @@ static void subscr_named_msg_event(void *usr_handle,
dbg("subscr_named_msg_event: orig = %x own = %x,\n",
orig->node, tipc_own_addr);
if (size && (size != sizeof(struct tipc_subscr))) {
warn("Received tipc_subscr of invalid size\n");
warn("Subscriber rejected, invalid subscription size\n");
return;
}
......@@ -395,7 +395,7 @@ static void subscr_named_msg_event(void *usr_handle,
subscriber = kmalloc(sizeof(struct subscriber), GFP_ATOMIC);
if (subscriber == NULL) {
warn("Memory squeeze; ignoring subscriber setup\n");
warn("Subscriber rejected, no memory\n");
return;
}
memset(subscriber, 0, sizeof(struct subscriber));
......@@ -403,7 +403,7 @@ static void subscr_named_msg_event(void *usr_handle,
INIT_LIST_HEAD(&subscriber->subscriber_list);
subscriber->ref = tipc_ref_acquire(subscriber, &subscriber->lock);
if (subscriber->ref == 0) {
warn("Failed to acquire subscriber reference\n");
warn("Subscriber rejected, reference table exhausted\n");
kfree(subscriber);
return;
}
......@@ -422,7 +422,7 @@ static void subscr_named_msg_event(void *usr_handle,
NULL,
&subscriber->port_ref);
if (subscriber->port_ref == 0) {
warn("Memory squeeze; failed to create subscription port\n");
warn("Subscriber rejected, unable to create port\n");
tipc_ref_discard(subscriber->ref);
kfree(subscriber);
return;
......
......@@ -44,19 +44,24 @@
struct _zone *tipc_zone_create(u32 addr)
{
struct _zone *z_ptr = NULL;
struct _zone *z_ptr;
u32 z_num;
if (!tipc_addr_domain_valid(addr))
if (!tipc_addr_domain_valid(addr)) {
err("Zone creation failed, invalid domain 0x%x\n", addr);
return NULL;
}
z_ptr = (struct _zone *)kmalloc(sizeof(*z_ptr), GFP_ATOMIC);
if (z_ptr != NULL) {
if (!z_ptr) {
warn("Zone creation failed, insufficient memory\n");
return NULL;
}
memset(z_ptr, 0, sizeof(*z_ptr));
z_num = tipc_zone(addr);
z_ptr->addr = tipc_addr(z_num, 0, 0);
tipc_net.zones[z_num] = z_ptr;
}
return z_ptr;
}
......
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