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: (36 commits)
  [Bluetooth] Fix HID disconnect NULL pointer dereference
  [Bluetooth] Add missing entry for Nokia DTL-4 PCMCIA card
  [Bluetooth] Add support for newer ANYCOM USB dongles
  [NET]: Can use __get_cpu_var() instead of per_cpu() in loopback driver.
  [IPV4] inet_peer: Group together avl_left, avl_right, v4daddr to speedup lookups on some CPUS
  [TCP]: One NET_INC_STATS() could be NET_INC_STATS_BH in tcp_v4_err()
  [NETFILTER]: Missing check for CAP_NET_ADMIN in iptables compat layer
  [NETPOLL]: initialize skb for UDP
  [IPV6]: Fix route.c warnings when multiple tables are disabled.
  [TG3]: Bump driver version and release date.
  [TG3]: Add lower bound checks for tx ring size.
  [TG3]: Fix set ring params tx ring size implementation
  [NET]: reduce per cpu ram used for loopback stats
  [IPv6] route: Fix prohibit and blackhole routing decision
  [DECNET]: Fix input routing bug
  [TCP]: Bound TSO defer time
  [IPv4] fib: Remove unused fib_config members
  [IPV6]: Always copy rt->u.dst.error when copying a rt6_info.
  [IPV6]: Make IPV6_SUBTREES depend on IPV6_MULTIPLE_TABLES.
  [IPV6]: Clean up BACKTRACK().
  ...
This commit is contained in:
Linus Torvalds 2006-10-20 10:27:38 -07:00
commit c144879164
34 changed files with 398 additions and 188 deletions

View File

@ -711,6 +711,7 @@ static void dtl1_release(struct pcmcia_device *link)
static struct pcmcia_device_id dtl1_ids[] = { static struct pcmcia_device_id dtl1_ids[] = {
PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d), PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d),
PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-4", 0xe1bfdd64, 0x9102bc82),
PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863), PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863),
PCMCIA_DEVICE_PROD_ID12("Socket", "CF+ Personal Network Card", 0xb38bcc2e, 0xe732bae3), PCMCIA_DEVICE_PROD_ID12("Socket", "CF+ Personal Network Card", 0xb38bcc2e, 0xe732bae3),
PCMCIA_DEVICE_NULL PCMCIA_DEVICE_NULL

View File

@ -118,6 +118,9 @@ static struct usb_device_id blacklist_ids[] = {
/* IBM/Lenovo ThinkPad with Broadcom chip */ /* IBM/Lenovo ThinkPad with Broadcom chip */
{ USB_DEVICE(0x0a5c, 0x201e), .driver_info = HCI_WRONG_SCO_MTU }, { USB_DEVICE(0x0a5c, 0x201e), .driver_info = HCI_WRONG_SCO_MTU },
/* ANYCOM Bluetooth USB-200 and USB-250 */
{ USB_DEVICE(0x0a5c, 0x2111), .driver_info = HCI_RESET },
/* Microsoft Wireless Transceiver for Bluetooth 2.0 */ /* Microsoft Wireless Transceiver for Bluetooth 2.0 */
{ USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET }, { USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET },

View File

@ -58,7 +58,11 @@
#include <linux/tcp.h> #include <linux/tcp.h>
#include <linux/percpu.h> #include <linux/percpu.h>
static DEFINE_PER_CPU(struct net_device_stats, loopback_stats); struct pcpu_lstats {
unsigned long packets;
unsigned long bytes;
};
static DEFINE_PER_CPU(struct pcpu_lstats, pcpu_lstats);
#define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16) #define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16)
@ -128,7 +132,7 @@ static void emulate_large_send_offload(struct sk_buff *skb)
*/ */
static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
struct net_device_stats *lb_stats; struct pcpu_lstats *lb_stats;
skb_orphan(skb); skb_orphan(skb);
@ -149,16 +153,14 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
#endif #endif
dev->last_rx = jiffies; dev->last_rx = jiffies;
lb_stats = &per_cpu(loopback_stats, get_cpu()); /* it's OK to use __get_cpu_var() because BHs are off */
lb_stats->rx_bytes += skb->len; lb_stats = &__get_cpu_var(pcpu_lstats);
lb_stats->tx_bytes = lb_stats->rx_bytes; lb_stats->bytes += skb->len;
lb_stats->rx_packets++; lb_stats->packets++;
lb_stats->tx_packets = lb_stats->rx_packets;
put_cpu();
netif_rx(skb); netif_rx(skb);
return(0); return 0;
} }
static struct net_device_stats loopback_stats; static struct net_device_stats loopback_stats;
@ -166,20 +168,21 @@ static struct net_device_stats loopback_stats;
static struct net_device_stats *get_stats(struct net_device *dev) static struct net_device_stats *get_stats(struct net_device *dev)
{ {
struct net_device_stats *stats = &loopback_stats; struct net_device_stats *stats = &loopback_stats;
unsigned long bytes = 0;
unsigned long packets = 0;
int i; int i;
memset(stats, 0, sizeof(struct net_device_stats));
for_each_possible_cpu(i) { for_each_possible_cpu(i) {
struct net_device_stats *lb_stats; const struct pcpu_lstats *lb_stats;
lb_stats = &per_cpu(loopback_stats, i); lb_stats = &per_cpu(pcpu_lstats, i);
stats->rx_bytes += lb_stats->rx_bytes; bytes += lb_stats->bytes;
stats->tx_bytes += lb_stats->tx_bytes; packets += lb_stats->packets;
stats->rx_packets += lb_stats->rx_packets;
stats->tx_packets += lb_stats->tx_packets;
} }
stats->rx_packets = packets;
stats->tx_packets = packets;
stats->rx_bytes = bytes;
stats->tx_bytes = bytes;
return stats; return stats;
} }

View File

@ -68,8 +68,8 @@
#define DRV_MODULE_NAME "tg3" #define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": " #define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "3.66" #define DRV_MODULE_VERSION "3.67"
#define DRV_MODULE_RELDATE "September 23, 2006" #define DRV_MODULE_RELDATE "October 18, 2006"
#define TG3_DEF_MAC_MODE 0 #define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0 #define TG3_DEF_RX_MODE 0
@ -129,7 +129,7 @@
#define RX_JUMBO_PKT_BUF_SZ (9046 + tp->rx_offset + 64) #define RX_JUMBO_PKT_BUF_SZ (9046 + tp->rx_offset + 64)
/* minimum number of free TX descriptors required to wake up TX process */ /* minimum number of free TX descriptors required to wake up TX process */
#define TG3_TX_WAKEUP_THRESH (TG3_TX_RING_SIZE / 4) #define TG3_TX_WAKEUP_THRESH(tp) ((tp)->tx_pending / 4)
/* number of ETHTOOL_GSTATS u64's */ /* number of ETHTOOL_GSTATS u64's */
#define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64)) #define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64))
@ -3075,10 +3075,10 @@ static void tg3_tx(struct tg3 *tp)
smp_mb(); smp_mb();
if (unlikely(netif_queue_stopped(tp->dev) && if (unlikely(netif_queue_stopped(tp->dev) &&
(tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH))) { (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)))) {
netif_tx_lock(tp->dev); netif_tx_lock(tp->dev);
if (netif_queue_stopped(tp->dev) && if (netif_queue_stopped(tp->dev) &&
(tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH)) (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)))
netif_wake_queue(tp->dev); netif_wake_queue(tp->dev);
netif_tx_unlock(tp->dev); netif_tx_unlock(tp->dev);
} }
@ -3928,7 +3928,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
tp->tx_prod = entry; tp->tx_prod = entry;
if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) { if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
netif_stop_queue(dev); netif_stop_queue(dev);
if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH) if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp))
netif_wake_queue(tp->dev); netif_wake_queue(tp->dev);
} }
@ -4143,7 +4143,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
tp->tx_prod = entry; tp->tx_prod = entry;
if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) { if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
netif_stop_queue(dev); netif_stop_queue(dev);
if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH) if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp))
netif_wake_queue(tp->dev); netif_wake_queue(tp->dev);
} }
@ -8106,7 +8106,10 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) || if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) ||
(ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) || (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
(ering->tx_pending > TG3_TX_RING_SIZE - 1)) (ering->tx_pending > TG3_TX_RING_SIZE - 1) ||
(ering->tx_pending <= MAX_SKB_FRAGS) ||
((tp->tg3_flags2 & TG3_FLG2_HW_TSO_1_BUG) &&
(ering->tx_pending <= (MAX_SKB_FRAGS * 3))))
return -EINVAL; return -EINVAL;
if (netif_running(dev)) { if (netif_running(dev)) {

View File

@ -342,6 +342,8 @@ struct tcp_sock {
unsigned long last_synq_overflow; unsigned long last_synq_overflow;
__u32 tso_deferred;
/* Receiver side RTT estimation */ /* Receiver side RTT estimation */
struct { struct {
__u32 rtt; __u32 rtt;

View File

@ -129,6 +129,7 @@ static inline unsigned int tipc_node(__u32 addr)
#define TIPC_SUB_PORTS 0x01 /* filter for port availability */ #define TIPC_SUB_PORTS 0x01 /* filter for port availability */
#define TIPC_SUB_SERVICE 0x02 /* filter for service availability */ #define TIPC_SUB_SERVICE 0x02 /* filter for service availability */
#define TIPC_SUB_CANCEL 0x04 /* cancel a subscription */
#if 0 #if 0
/* The following filter options are not currently implemented */ /* The following filter options are not currently implemented */
#define TIPC_SUB_NO_BIND_EVTS 0x04 /* filter out "publish" events */ #define TIPC_SUB_NO_BIND_EVTS 0x04 /* filter out "publish" events */

View File

@ -17,14 +17,15 @@
struct inet_peer struct inet_peer
{ {
/* group together avl_left,avl_right,v4daddr to speedup lookups */
struct inet_peer *avl_left, *avl_right; struct inet_peer *avl_left, *avl_right;
__be32 v4daddr; /* peer's address */
__u16 avl_height;
__u16 ip_id_count; /* IP ID for the next packet */
struct inet_peer *unused_next, **unused_prevp; struct inet_peer *unused_next, **unused_prevp;
__u32 dtime; /* the time of last use of not __u32 dtime; /* the time of last use of not
* referenced entries */ * referenced entries */
atomic_t refcnt; atomic_t refcnt;
__be32 v4daddr; /* peer's address */
__u16 avl_height;
__u16 ip_id_count; /* IP ID for the next packet */
atomic_t rid; /* Frag reception counter */ atomic_t rid; /* Frag reception counter */
__u32 tcp_ts; __u32 tcp_ts;
unsigned long tcp_ts_stamp; unsigned long tcp_ts_stamp;

View File

@ -36,13 +36,6 @@ struct route_info {
#define RT6_LOOKUP_F_REACHABLE 0x2 #define RT6_LOOKUP_F_REACHABLE 0x2
#define RT6_LOOKUP_F_HAS_SADDR 0x4 #define RT6_LOOKUP_F_HAS_SADDR 0x4
struct pol_chain {
int type;
int priority;
struct fib6_node *rules;
struct pol_chain *next;
};
extern struct rt6_info ip6_null_entry; extern struct rt6_info ip6_null_entry;
#ifdef CONFIG_IPV6_MULTIPLE_TABLES #ifdef CONFIG_IPV6_MULTIPLE_TABLES

View File

@ -21,17 +21,14 @@
#include <net/fib_rules.h> #include <net/fib_rules.h>
struct fib_config { struct fib_config {
u8 fc_family;
u8 fc_dst_len; u8 fc_dst_len;
u8 fc_src_len;
u8 fc_tos; u8 fc_tos;
u8 fc_protocol; u8 fc_protocol;
u8 fc_scope; u8 fc_scope;
u8 fc_type; u8 fc_type;
/* 1 byte unused */ /* 3 bytes unused */
u32 fc_table; u32 fc_table;
__be32 fc_dst; __be32 fc_dst;
__be32 fc_src;
__be32 fc_gw; __be32 fc_gw;
int fc_oif; int fc_oif;
u32 fc_flags; u32 fc_flags;

View File

@ -507,12 +507,10 @@ static int hidp_session(void *arg)
hidp_del_timer(session); hidp_del_timer(session);
if (intr_sk->sk_state != BT_CONNECTED)
wait_event_timeout(*(ctrl_sk->sk_sleep), (ctrl_sk->sk_state == BT_CLOSED), HZ);
fput(session->intr_sock->file); fput(session->intr_sock->file);
wait_event_timeout(*(intr_sk->sk_sleep), (intr_sk->sk_state == BT_CLOSED), HZ); wait_event_timeout(*(ctrl_sk->sk_sleep),
(ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
fput(session->ctrl_sock->file); fput(session->ctrl_sock->file);

View File

@ -335,13 +335,13 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
memcpy(skb->data, msg, len); memcpy(skb->data, msg, len);
skb->len += len; skb->len += len;
udph = (struct udphdr *) skb_push(skb, sizeof(*udph)); skb->h.uh = udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
udph->source = htons(np->local_port); udph->source = htons(np->local_port);
udph->dest = htons(np->remote_port); udph->dest = htons(np->remote_port);
udph->len = htons(udp_len); udph->len = htons(udp_len);
udph->check = 0; udph->check = 0;
iph = (struct iphdr *)skb_push(skb, sizeof(*iph)); skb->nh.iph = iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
/* iph->version = 4; iph->ihl = 5; */ /* iph->version = 4; iph->ihl = 5; */
put_unaligned(0x45, (unsigned char *)iph); put_unaligned(0x45, (unsigned char *)iph);
@ -357,8 +357,8 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
eth = (struct ethhdr *) skb_push(skb, ETH_HLEN); eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
skb->mac.raw = skb->data;
eth->h_proto = htons(ETH_P_IP); skb->protocol = eth->h_proto = htons(ETH_P_IP);
memcpy(eth->h_source, np->local_mac, 6); memcpy(eth->h_source, np->local_mac, 6);
memcpy(eth->h_dest, np->remote_mac, 6); memcpy(eth->h_dest, np->remote_mac, 6);

View File

@ -1275,7 +1275,6 @@ static int dn_route_input_slow(struct sk_buff *skb)
goto e_inval; goto e_inval;
res.type = RTN_LOCAL; res.type = RTN_LOCAL;
flags |= RTCF_DIRECTSRC;
} else { } else {
__le16 src_map = fl.fld_src; __le16 src_map = fl.fld_src;
free_res = 1; free_res = 1;
@ -1346,7 +1345,7 @@ static int dn_route_input_slow(struct sk_buff *skb)
goto make_route; goto make_route;
/* Packet was intra-ethernet, so we know its on-link */ /* Packet was intra-ethernet, so we know its on-link */
if (cb->rt_flags | DN_RT_F_IE) { if (cb->rt_flags & DN_RT_F_IE) {
gateway = cb->src; gateway = cb->src;
flags |= RTCF_DIRECTSRC; flags |= RTCF_DIRECTSRC;
goto make_route; goto make_route;

View File

@ -482,9 +482,7 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
memset(cfg, 0, sizeof(*cfg)); memset(cfg, 0, sizeof(*cfg));
rtm = nlmsg_data(nlh); rtm = nlmsg_data(nlh);
cfg->fc_family = rtm->rtm_family;
cfg->fc_dst_len = rtm->rtm_dst_len; cfg->fc_dst_len = rtm->rtm_dst_len;
cfg->fc_src_len = rtm->rtm_src_len;
cfg->fc_tos = rtm->rtm_tos; cfg->fc_tos = rtm->rtm_tos;
cfg->fc_table = rtm->rtm_table; cfg->fc_table = rtm->rtm_table;
cfg->fc_protocol = rtm->rtm_protocol; cfg->fc_protocol = rtm->rtm_protocol;
@ -501,9 +499,6 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
case RTA_DST: case RTA_DST:
cfg->fc_dst = nla_get_be32(attr); cfg->fc_dst = nla_get_be32(attr);
break; break;
case RTA_SRC:
cfg->fc_src = nla_get_be32(attr);
break;
case RTA_OIF: case RTA_OIF:
cfg->fc_oif = nla_get_u32(attr); cfg->fc_oif = nla_get_u32(attr);
break; break;

View File

@ -1932,6 +1932,9 @@ compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
{ {
int ret; int ret;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
switch (cmd) { switch (cmd) {
case IPT_SO_GET_INFO: case IPT_SO_GET_INFO:
ret = get_info(user, len, 1); ret = get_info(user, len, 1);

View File

@ -373,7 +373,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
seq = ntohl(th->seq); seq = ntohl(th->seq);
if (sk->sk_state != TCP_LISTEN && if (sk->sk_state != TCP_LISTEN &&
!between(seq, tp->snd_una, tp->snd_nxt)) { !between(seq, tp->snd_una, tp->snd_nxt)) {
NET_INC_STATS(LINUX_MIB_OUTOFWINDOWICMPS); NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
goto out; goto out;
} }

View File

@ -1096,10 +1096,14 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
u32 send_win, cong_win, limit, in_flight; u32 send_win, cong_win, limit, in_flight;
if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)
return 0; goto send_now;
if (icsk->icsk_ca_state != TCP_CA_Open) if (icsk->icsk_ca_state != TCP_CA_Open)
return 0; goto send_now;
/* Defer for less than two clock ticks. */
if (!tp->tso_deferred && ((jiffies<<1)>>1) - (tp->tso_deferred>>1) > 1)
goto send_now;
in_flight = tcp_packets_in_flight(tp); in_flight = tcp_packets_in_flight(tp);
@ -1115,7 +1119,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
/* If a full-sized TSO skb can be sent, do it. */ /* If a full-sized TSO skb can be sent, do it. */
if (limit >= 65536) if (limit >= 65536)
return 0; goto send_now;
if (sysctl_tcp_tso_win_divisor) { if (sysctl_tcp_tso_win_divisor) {
u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache); u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache);
@ -1125,7 +1129,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
*/ */
chunk /= sysctl_tcp_tso_win_divisor; chunk /= sysctl_tcp_tso_win_divisor;
if (limit >= chunk) if (limit >= chunk)
return 0; goto send_now;
} else { } else {
/* Different approach, try not to defer past a single /* Different approach, try not to defer past a single
* ACK. Receiver should ACK every other full sized * ACK. Receiver should ACK every other full sized
@ -1133,11 +1137,17 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
* then send now. * then send now.
*/ */
if (limit > tcp_max_burst(tp) * tp->mss_cache) if (limit > tcp_max_burst(tp) * tp->mss_cache)
return 0; goto send_now;
} }
/* Ok, it looks like it is advisable to defer. */ /* Ok, it looks like it is advisable to defer. */
tp->tso_deferred = 1 | (jiffies<<1);
return 1; return 1;
send_now:
tp->tso_deferred = 0;
return 0;
} }
/* Create a new MTU probe if we are ready. /* Create a new MTU probe if we are ready.

View File

@ -175,9 +175,16 @@ config IPV6_TUNNEL
If unsure, say N. If unsure, say N.
config IPV6_MULTIPLE_TABLES
bool "IPv6: Multiple Routing Tables"
depends on IPV6 && EXPERIMENTAL
select FIB_RULES
---help---
Support multiple routing tables.
config IPV6_SUBTREES config IPV6_SUBTREES
bool "IPv6: source address based routing" bool "IPv6: source address based routing"
depends on IPV6 && EXPERIMENTAL depends on IPV6_MULTIPLE_TABLES
---help--- ---help---
Enable routing by source address or prefix. Enable routing by source address or prefix.
@ -189,13 +196,6 @@ config IPV6_SUBTREES
If unsure, say N. If unsure, say N.
config IPV6_MULTIPLE_TABLES
bool "IPv6: Multiple Routing Tables"
depends on IPV6 && EXPERIMENTAL
select FIB_RULES
---help---
Support multiple routing tables.
config IPV6_ROUTE_FWMARK config IPV6_ROUTE_FWMARK
bool "IPv6: use netfilter MARK value as routing key" bool "IPv6: use netfilter MARK value as routing key"
depends on IPV6_MULTIPLE_TABLES && NETFILTER depends on IPV6_MULTIPLE_TABLES && NETFILTER

View File

@ -141,6 +141,10 @@ struct rt6_info ip6_null_entry = {
#ifdef CONFIG_IPV6_MULTIPLE_TABLES #ifdef CONFIG_IPV6_MULTIPLE_TABLES
static int ip6_pkt_prohibit(struct sk_buff *skb);
static int ip6_pkt_prohibit_out(struct sk_buff *skb);
static int ip6_pkt_blk_hole(struct sk_buff *skb);
struct rt6_info ip6_prohibit_entry = { struct rt6_info ip6_prohibit_entry = {
.u = { .u = {
.dst = { .dst = {
@ -150,8 +154,8 @@ struct rt6_info ip6_prohibit_entry = {
.obsolete = -1, .obsolete = -1,
.error = -EACCES, .error = -EACCES,
.metrics = { [RTAX_HOPLIMIT - 1] = 255, }, .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
.input = ip6_pkt_discard, .input = ip6_pkt_prohibit,
.output = ip6_pkt_discard_out, .output = ip6_pkt_prohibit_out,
.ops = &ip6_dst_ops, .ops = &ip6_dst_ops,
.path = (struct dst_entry*)&ip6_prohibit_entry, .path = (struct dst_entry*)&ip6_prohibit_entry,
} }
@ -170,8 +174,8 @@ struct rt6_info ip6_blk_hole_entry = {
.obsolete = -1, .obsolete = -1,
.error = -EINVAL, .error = -EINVAL,
.metrics = { [RTAX_HOPLIMIT - 1] = 255, }, .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
.input = ip6_pkt_discard, .input = ip6_pkt_blk_hole,
.output = ip6_pkt_discard_out, .output = ip6_pkt_blk_hole,
.ops = &ip6_dst_ops, .ops = &ip6_dst_ops,
.path = (struct dst_entry*)&ip6_blk_hole_entry, .path = (struct dst_entry*)&ip6_blk_hole_entry,
} }
@ -484,7 +488,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
do { \ do { \
if (rt == &ip6_null_entry) { \ if (rt == &ip6_null_entry) { \
struct fib6_node *pn; \ struct fib6_node *pn; \
while (fn) { \ while (1) { \
if (fn->fn_flags & RTN_TL_ROOT) \ if (fn->fn_flags & RTN_TL_ROOT) \
goto out; \ goto out; \
pn = fn->parent; \ pn = fn->parent; \
@ -618,8 +622,6 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d
ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); ipv6_addr_copy(&rt->rt6i_dst.addr, daddr);
rt->rt6i_dst.plen = 128; rt->rt6i_dst.plen = 128;
rt->rt6i_flags |= RTF_CACHE; rt->rt6i_flags |= RTF_CACHE;
if (rt->rt6i_flags & RTF_REJECT)
rt->u.dst.error = ort->u.dst.error;
rt->u.dst.flags |= DST_HOST; rt->u.dst.flags |= DST_HOST;
rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop); rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop);
} }
@ -1540,6 +1542,7 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
rt->u.dst.output = ort->u.dst.output; rt->u.dst.output = ort->u.dst.output;
memcpy(rt->u.dst.metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32)); memcpy(rt->u.dst.metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32));
rt->u.dst.error = ort->u.dst.error;
rt->u.dst.dev = ort->u.dst.dev; rt->u.dst.dev = ort->u.dst.dev;
if (rt->u.dst.dev) if (rt->u.dst.dev)
dev_hold(rt->u.dst.dev); dev_hold(rt->u.dst.dev);
@ -1743,24 +1746,50 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
* Drop the packet on the floor * Drop the packet on the floor
*/ */
static int ip6_pkt_discard(struct sk_buff *skb) static inline int ip6_pkt_drop(struct sk_buff *skb, int code)
{ {
int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); int type = ipv6_addr_type(&skb->nh.ipv6h->daddr);
if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED)
IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS); IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS);
IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev); icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev);
kfree_skb(skb); kfree_skb(skb);
return 0; return 0;
} }
static int ip6_pkt_discard(struct sk_buff *skb)
{
return ip6_pkt_drop(skb, ICMPV6_NOROUTE);
}
static int ip6_pkt_discard_out(struct sk_buff *skb) static int ip6_pkt_discard_out(struct sk_buff *skb)
{ {
skb->dev = skb->dst->dev; skb->dev = skb->dst->dev;
return ip6_pkt_discard(skb); return ip6_pkt_discard(skb);
} }
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
static int ip6_pkt_prohibit(struct sk_buff *skb)
{
return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED);
}
static int ip6_pkt_prohibit_out(struct sk_buff *skb)
{
skb->dev = skb->dst->dev;
return ip6_pkt_prohibit(skb);
}
static int ip6_pkt_blk_hole(struct sk_buff *skb)
{
kfree_skb(skb);
return 0;
}
#endif
/* /*
* Allocate a dst for local (unicast / anycast) address. * Allocate a dst for local (unicast / anycast) address.
*/ */

View File

@ -25,12 +25,14 @@
static struct dst_ops xfrm6_dst_ops; static struct dst_ops xfrm6_dst_ops;
static struct xfrm_policy_afinfo xfrm6_policy_afinfo; static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
static int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl) static int xfrm6_dst_lookup(struct xfrm_dst **xdst, struct flowi *fl)
{ {
int err = 0; struct dst_entry *dst = ip6_route_output(NULL, fl);
*dst = (struct xfrm_dst*)ip6_route_output(NULL, fl); int err = dst->error;
if (!*dst) if (!err)
err = -ENETUNREACH; *xdst = (struct xfrm_dst *) dst;
else
dst_release(dst);
return err; return err;
} }

View File

@ -215,17 +215,17 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
} }
dst = ip6_route_output(NULL, &fl); dst = ip6_route_output(NULL, &fl);
if (dst) { if (!dst->error) {
struct rt6_info *rt; struct rt6_info *rt;
rt = (struct rt6_info *)dst; rt = (struct rt6_info *)dst;
SCTP_DEBUG_PRINTK( SCTP_DEBUG_PRINTK(
"rt6_dst:" NIP6_FMT " rt6_src:" NIP6_FMT "\n", "rt6_dst:" NIP6_FMT " rt6_src:" NIP6_FMT "\n",
NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr)); NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr));
} else { return dst;
SCTP_DEBUG_PRINTK("NO ROUTE\n");
} }
SCTP_DEBUG_PRINTK("NO ROUTE\n");
return dst; dst_release(dst);
return NULL;
} }
/* Returns the number of consecutive initial bits that match in the 2 ipv6 /* Returns the number of consecutive initial bits that match in the 2 ipv6

View File

@ -821,7 +821,7 @@ out:
* addrs is a pointer to an array of one or more socket addresses. Each * addrs is a pointer to an array of one or more socket addresses. Each
* address is contained in its appropriate structure (i.e. struct * address is contained in its appropriate structure (i.e. struct
* sockaddr_in or struct sockaddr_in6) the family of the address type * sockaddr_in or struct sockaddr_in6) the family of the address type
* must be used to distengish the address length (note that this * must be used to distinguish the address length (note that this
* representation is termed a "packed array" of addresses). The caller * representation is termed a "packed array" of addresses). The caller
* specifies the number of addresses in the array with addrcnt. * specifies the number of addresses in the array with addrcnt.
* *

View File

@ -2,7 +2,7 @@
* net/tipc/bearer.c: TIPC bearer code * net/tipc/bearer.c: TIPC bearer code
* *
* Copyright (c) 1996-2006, Ericsson AB * Copyright (c) 1996-2006, Ericsson AB
* Copyright (c) 2004-2005, Wind River Systems * Copyright (c) 2004-2006, Wind River Systems
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -191,14 +191,14 @@ void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a)
if ((i < media_count) && (m_ptr->addr2str != NULL)) { if ((i < media_count) && (m_ptr->addr2str != NULL)) {
char addr_str[MAX_ADDR_STR]; char addr_str[MAX_ADDR_STR];
tipc_printf(pb, "%s(%s) ", m_ptr->name, tipc_printf(pb, "%s(%s)", m_ptr->name,
m_ptr->addr2str(a, addr_str, sizeof(addr_str))); m_ptr->addr2str(a, addr_str, sizeof(addr_str)));
} else { } else {
unchar *addr = (unchar *)&a->dev_addr; unchar *addr = (unchar *)&a->dev_addr;
tipc_printf(pb, "UNKNOWN(%u):", media_type); tipc_printf(pb, "UNKNOWN(%u)", media_type);
for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++) { for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++) {
tipc_printf(pb, "%02x ", addr[i]); tipc_printf(pb, "-%02x", addr[i]);
} }
} }
} }

View File

@ -2,7 +2,7 @@
* net/tipc/config.c: TIPC configuration management code * net/tipc/config.c: TIPC configuration management code
* *
* Copyright (c) 2002-2006, Ericsson AB * Copyright (c) 2002-2006, Ericsson AB
* Copyright (c) 2004-2005, Wind River Systems * Copyright (c) 2004-2006, Wind River Systems
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -613,7 +613,8 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area
rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id); rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id);
break; break;
default: default:
rep_tlv_buf = NULL; rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
" (unknown command)");
break; break;
} }

View File

@ -57,7 +57,7 @@ void tipc_socket_stop(void);
int tipc_netlink_start(void); int tipc_netlink_start(void);
void tipc_netlink_stop(void); void tipc_netlink_stop(void);
#define TIPC_MOD_VER "1.6.1" #define TIPC_MOD_VER "1.6.2"
#ifndef CONFIG_TIPC_ZONES #ifndef CONFIG_TIPC_ZONES
#define CONFIG_TIPC_ZONES 3 #define CONFIG_TIPC_ZONES 3
@ -90,7 +90,7 @@ int tipc_random;
atomic_t tipc_user_count = ATOMIC_INIT(0); atomic_t tipc_user_count = ATOMIC_INIT(0);
const char tipc_alphabet[] = const char tipc_alphabet[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.";
/* configurable TIPC parameters */ /* configurable TIPC parameters */

View File

@ -65,7 +65,7 @@
#define assert(i) BUG_ON(!(i)) #define assert(i) BUG_ON(!(i))
struct tipc_msg; struct tipc_msg;
extern struct print_buf *TIPC_CONS, *TIPC_LOG; extern struct print_buf *TIPC_NULL, *TIPC_CONS, *TIPC_LOG;
extern struct print_buf *TIPC_TEE(struct print_buf *, struct print_buf *); extern struct print_buf *TIPC_TEE(struct print_buf *, struct print_buf *);
void tipc_msg_print(struct print_buf*,struct tipc_msg *,const char*); void tipc_msg_print(struct print_buf*,struct tipc_msg *,const char*);
void tipc_printf(struct print_buf *, const char *fmt, ...); void tipc_printf(struct print_buf *, const char *fmt, ...);
@ -83,9 +83,9 @@ void tipc_dump(struct print_buf*,const char *fmt, ...);
#define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_WARNING "TIPC: " fmt, ## arg) #define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_WARNING "TIPC: " fmt, ## arg)
#define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_NOTICE "TIPC: " fmt, ## arg) #define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_NOTICE "TIPC: " fmt, ## arg)
#define dbg(fmt, arg...) do {if (DBG_OUTPUT) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0) #define dbg(fmt, arg...) do {if (DBG_OUTPUT != TIPC_NULL) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0)
#define msg_dbg(msg, txt) do {if (DBG_OUTPUT) tipc_msg_print(DBG_OUTPUT, msg, txt);} while(0) #define msg_dbg(msg, txt) do {if (DBG_OUTPUT != TIPC_NULL) tipc_msg_print(DBG_OUTPUT, msg, txt);} while(0)
#define dump(fmt, arg...) do {if (DBG_OUTPUT) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0) #define dump(fmt, arg...) do {if (DBG_OUTPUT != TIPC_NULL) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0)
/* /*
@ -94,11 +94,11 @@ void tipc_dump(struct print_buf*,const char *fmt, ...);
* here, or on a per .c file basis, by redefining these symbols. The following * here, or on a per .c file basis, by redefining these symbols. The following
* print buffer options are available: * print buffer options are available:
* *
* NULL : Output to null print buffer (i.e. print nowhere) * TIPC_NULL : null buffer (i.e. print nowhere)
* TIPC_CONS : Output to system console * TIPC_CONS : system console
* TIPC_LOG : Output to TIPC log buffer * TIPC_LOG : TIPC log buffer
* &buf : Output to user-defined buffer (struct print_buf *) * &buf : user-defined buffer (struct print_buf *)
* TIPC_TEE(&buf_a,&buf_b) : Output to two print buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG) ) * TIPC_TEE(&buf_a,&buf_b) : list of buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG))
*/ */
#ifndef TIPC_OUTPUT #ifndef TIPC_OUTPUT
@ -106,7 +106,7 @@ void tipc_dump(struct print_buf*,const char *fmt, ...);
#endif #endif
#ifndef DBG_OUTPUT #ifndef DBG_OUTPUT
#define DBG_OUTPUT NULL #define DBG_OUTPUT TIPC_NULL
#endif #endif
#else #else
@ -136,7 +136,7 @@ void tipc_dump(struct print_buf*,const char *fmt, ...);
#define TIPC_OUTPUT TIPC_CONS #define TIPC_OUTPUT TIPC_CONS
#undef DBG_OUTPUT #undef DBG_OUTPUT
#define DBG_OUTPUT NULL #define DBG_OUTPUT TIPC_NULL
#endif #endif
@ -275,11 +275,15 @@ static inline void k_term_timer(struct timer_list *timer)
/* /*
* TIPC message buffer code * TIPC message buffer code
* *
* TIPC message buffer headroom leaves room for 14 byte Ethernet header, * TIPC message buffer headroom reserves space for a link-level header
* (in case the message is sent off-node),
* while ensuring TIPC header is word aligned for quicker access * while ensuring TIPC header is word aligned for quicker access
*
* The largest header currently supported is 18 bytes, which is used when
* the standard 14 byte Ethernet header has 4 added bytes for VLAN info
*/ */
#define BUF_HEADROOM 16u #define BUF_HEADROOM 20u
struct tipc_skb_cb { struct tipc_skb_cb {
void *handle; void *handle;

View File

@ -1,8 +1,8 @@
/* /*
* net/tipc/dbg.c: TIPC print buffer routines for debuggign * net/tipc/dbg.c: TIPC print buffer routines for debugging
* *
* Copyright (c) 1996-2006, Ericsson AB * Copyright (c) 1996-2006, Ericsson AB
* Copyright (c) 2005, Wind River Systems * Copyright (c) 2005-2006, Wind River Systems
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -38,11 +38,12 @@
#include "config.h" #include "config.h"
#include "dbg.h" #include "dbg.h"
#define MAX_STRING 512 static char print_string[TIPC_PB_MAX_STR];
static char print_string[MAX_STRING];
static DEFINE_SPINLOCK(print_lock); static DEFINE_SPINLOCK(print_lock);
static struct print_buf null_buf = { NULL, 0, NULL, NULL };
struct print_buf *TIPC_NULL = &null_buf;
static struct print_buf cons_buf = { NULL, 0, NULL, NULL }; static struct print_buf cons_buf = { NULL, 0, NULL, NULL };
struct print_buf *TIPC_CONS = &cons_buf; struct print_buf *TIPC_CONS = &cons_buf;
@ -62,68 +63,83 @@ struct print_buf *TIPC_LOG = &log_buf;
/* /*
* Locking policy when using print buffers. * Locking policy when using print buffers.
* *
* 1) Routines of the form printbuf_XXX() rely on the caller to prevent * The following routines use 'print_lock' for protection:
* simultaneous use of the print buffer(s) being manipulated. * 1) tipc_printf() - to protect its print buffer(s) and 'print_string'
* 2) tipc_printf() uses 'print_lock' to prevent simultaneous use of * 2) TIPC_TEE() - to protect its print buffer(s)
* 'print_string' and to protect its print buffer(s). * 3) tipc_dump() - to protect its print buffer(s) and 'print_string'
* 3) TIPC_TEE() uses 'print_lock' to protect its print buffer(s). * 4) tipc_log_XXX() - to protect TIPC_LOG
* 4) Routines of the form log_XXX() uses 'print_lock' to protect TIPC_LOG. *
* All routines of the form tipc_printbuf_XXX() rely on the caller to prevent
* simultaneous use of the print buffer(s) being manipulated.
*/ */
/** /**
* tipc_printbuf_init - initialize print buffer to empty * tipc_printbuf_init - initialize print buffer to empty
* @pb: pointer to print buffer structure
* @raw: pointer to character array used by print buffer
* @size: size of character array
*
* Makes the print buffer a null device that discards anything written to it
* if the character array is too small (or absent).
*/ */
void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 sz) void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size)
{ {
if (!pb || !raw || (sz < (MAX_STRING + 1))) pb->buf = raw;
return; pb->crs = raw;
pb->size = size;
pb->crs = pb->buf = raw;
pb->size = sz;
pb->next = NULL; pb->next = NULL;
pb->buf[0] = 0;
pb->buf[sz-1] = ~0; if (size < TIPC_PB_MIN_SIZE) {
pb->buf = NULL;
} else if (raw) {
pb->buf[0] = 0;
pb->buf[size-1] = ~0;
}
} }
/** /**
* tipc_printbuf_reset - reinitialize print buffer to empty state * tipc_printbuf_reset - reinitialize print buffer to empty state
* @pb: pointer to print buffer structure
*/ */
void tipc_printbuf_reset(struct print_buf *pb) void tipc_printbuf_reset(struct print_buf *pb)
{ {
if (pb && pb->buf) tipc_printbuf_init(pb, pb->buf, pb->size);
tipc_printbuf_init(pb, pb->buf, pb->size);
} }
/** /**
* tipc_printbuf_empty - test if print buffer is in empty state * tipc_printbuf_empty - test if print buffer is in empty state
* @pb: pointer to print buffer structure
*
* Returns non-zero if print buffer is empty.
*/ */
int tipc_printbuf_empty(struct print_buf *pb) int tipc_printbuf_empty(struct print_buf *pb)
{ {
return (!pb || !pb->buf || (pb->crs == pb->buf)); return (!pb->buf || (pb->crs == pb->buf));
} }
/** /**
* tipc_printbuf_validate - check for print buffer overflow * tipc_printbuf_validate - check for print buffer overflow
* @pb: pointer to print buffer structure
* *
* Verifies that a print buffer has captured all data written to it. * Verifies that a print buffer has captured all data written to it.
* If data has been lost, linearize buffer and prepend an error message * If data has been lost, linearize buffer and prepend an error message
* *
* Returns length of print buffer data string (including trailing NULL) * Returns length of print buffer data string (including trailing NUL)
*/ */
int tipc_printbuf_validate(struct print_buf *pb) int tipc_printbuf_validate(struct print_buf *pb)
{ {
char *err = " *** PRINT BUFFER WRAPPED AROUND ***\n"; char *err = "\n\n*** PRINT BUFFER OVERFLOW ***\n\n";
char *cp_buf; char *cp_buf;
struct print_buf cb; struct print_buf cb;
if (!pb || !pb->buf) if (!pb->buf)
return 0; return 0;
if (pb->buf[pb->size - 1] == '\0') { if (pb->buf[pb->size - 1] == 0) {
cp_buf = kmalloc(pb->size, GFP_ATOMIC); cp_buf = kmalloc(pb->size, GFP_ATOMIC);
if (cp_buf != NULL){ if (cp_buf != NULL){
tipc_printbuf_init(&cb, cp_buf, pb->size); tipc_printbuf_init(&cb, cp_buf, pb->size);
@ -141,6 +157,8 @@ int tipc_printbuf_validate(struct print_buf *pb)
/** /**
* tipc_printbuf_move - move print buffer contents to another print buffer * tipc_printbuf_move - move print buffer contents to another print buffer
* @pb_to: pointer to destination print buffer structure
* @pb_from: pointer to source print buffer structure
* *
* Current contents of destination print buffer (if any) are discarded. * Current contents of destination print buffer (if any) are discarded.
* Source print buffer becomes empty if a successful move occurs. * Source print buffer becomes empty if a successful move occurs.
@ -152,21 +170,22 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
/* Handle the cases where contents can't be moved */ /* Handle the cases where contents can't be moved */
if (!pb_to || !pb_to->buf) if (!pb_to->buf)
return; return;
if (!pb_from || !pb_from->buf) { if (!pb_from->buf) {
tipc_printbuf_reset(pb_to); tipc_printbuf_reset(pb_to);
return; return;
} }
if (pb_to->size < pb_from->size) { if (pb_to->size < pb_from->size) {
tipc_printbuf_reset(pb_to); tipc_printbuf_reset(pb_to);
tipc_printf(pb_to, "*** PRINT BUFFER OVERFLOW ***"); tipc_printf(pb_to, "*** PRINT BUFFER MOVE ERROR ***");
return; return;
} }
/* Copy data from char after cursor to end (if used) */ /* Copy data from char after cursor to end (if used) */
len = pb_from->buf + pb_from->size - pb_from->crs - 2; len = pb_from->buf + pb_from->size - pb_from->crs - 2;
if ((pb_from->buf[pb_from->size-1] == 0) && (len > 0)) { if ((pb_from->buf[pb_from->size-1] == 0) && (len > 0)) {
strcpy(pb_to->buf, pb_from->crs + 1); strcpy(pb_to->buf, pb_from->crs + 1);
@ -175,6 +194,7 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
pb_to->crs = pb_to->buf; pb_to->crs = pb_to->buf;
/* Copy data from start to cursor (always) */ /* Copy data from start to cursor (always) */
len = pb_from->crs - pb_from->buf; len = pb_from->crs - pb_from->buf;
strcpy(pb_to->crs, pb_from->buf); strcpy(pb_to->crs, pb_from->buf);
pb_to->crs += len; pb_to->crs += len;
@ -184,6 +204,8 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
/** /**
* tipc_printf - append formatted output to print buffer chain * tipc_printf - append formatted output to print buffer chain
* @pb: pointer to chain of print buffers (may be NULL)
* @fmt: formatted info to be printed
*/ */
void tipc_printf(struct print_buf *pb, const char *fmt, ...) void tipc_printf(struct print_buf *pb, const char *fmt, ...)
@ -195,8 +217,8 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...)
spin_lock_bh(&print_lock); spin_lock_bh(&print_lock);
FORMAT(print_string, chars_to_add, fmt); FORMAT(print_string, chars_to_add, fmt);
if (chars_to_add >= MAX_STRING) if (chars_to_add >= TIPC_PB_MAX_STR)
strcpy(print_string, "*** STRING TOO LONG ***"); strcpy(print_string, "*** PRINT BUFFER STRING TOO LONG ***");
while (pb) { while (pb) {
if (pb == TIPC_CONS) if (pb == TIPC_CONS)
@ -206,6 +228,10 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...)
if (chars_to_add <= chars_left) { if (chars_to_add <= chars_left) {
strcpy(pb->crs, print_string); strcpy(pb->crs, print_string);
pb->crs += chars_to_add; pb->crs += chars_to_add;
} else if (chars_to_add >= (pb->size - 1)) {
strcpy(pb->buf, print_string + chars_to_add + 1
- pb->size);
pb->crs = pb->buf + pb->size - 1;
} else { } else {
strcpy(pb->buf, print_string + chars_left); strcpy(pb->buf, print_string + chars_left);
save_char = print_string[chars_left]; save_char = print_string[chars_left];
@ -224,6 +250,10 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...)
/** /**
* TIPC_TEE - perform next output operation on both print buffers * TIPC_TEE - perform next output operation on both print buffers
* @b0: pointer to chain of print buffers (may be NULL)
* @b1: pointer to print buffer to add to chain
*
* Returns pointer to print buffer chain.
*/ */
struct print_buf *TIPC_TEE(struct print_buf *b0, struct print_buf *b1) struct print_buf *TIPC_TEE(struct print_buf *b0, struct print_buf *b1)
@ -232,8 +262,6 @@ struct print_buf *TIPC_TEE(struct print_buf *b0, struct print_buf *b1)
if (!b0 || (b0 == b1)) if (!b0 || (b0 == b1))
return b1; return b1;
if (!b1)
return b0;
spin_lock_bh(&print_lock); spin_lock_bh(&print_lock);
while (pb->next) { while (pb->next) {
@ -256,7 +284,7 @@ static void print_to_console(char *crs, int len)
int rest = len; int rest = len;
while (rest > 0) { while (rest > 0) {
int sz = rest < MAX_STRING ? rest : MAX_STRING; int sz = rest < TIPC_PB_MAX_STR ? rest : TIPC_PB_MAX_STR;
char c = crs[sz]; char c = crs[sz];
crs[sz] = 0; crs[sz] = 0;
@ -275,36 +303,48 @@ static void printbuf_dump(struct print_buf *pb)
{ {
int len; int len;
if (!pb->buf) {
printk("*** PRINT BUFFER NOT ALLOCATED ***");
return;
}
/* Dump print buffer from char after cursor to end (if used) */ /* Dump print buffer from char after cursor to end (if used) */
len = pb->buf + pb->size - pb->crs - 2; len = pb->buf + pb->size - pb->crs - 2;
if ((pb->buf[pb->size - 1] == 0) && (len > 0)) if ((pb->buf[pb->size - 1] == 0) && (len > 0))
print_to_console(pb->crs + 1, len); print_to_console(pb->crs + 1, len);
/* Dump print buffer from start to cursor (always) */ /* Dump print buffer from start to cursor (always) */
len = pb->crs - pb->buf; len = pb->crs - pb->buf;
print_to_console(pb->buf, len); print_to_console(pb->buf, len);
} }
/** /**
* tipc_dump - dump non-console print buffer(s) to console * tipc_dump - dump non-console print buffer(s) to console
* @pb: pointer to chain of print buffers
*/ */
void tipc_dump(struct print_buf *pb, const char *fmt, ...) void tipc_dump(struct print_buf *pb, const char *fmt, ...)
{ {
struct print_buf *pb_next;
int len; int len;
spin_lock_bh(&print_lock); spin_lock_bh(&print_lock);
FORMAT(TIPC_CONS->buf, len, fmt); FORMAT(print_string, len, fmt);
printk(TIPC_CONS->buf); printk(print_string);
for (; pb; pb = pb->next) { for (; pb; pb = pb->next) {
if (pb == TIPC_CONS) if (pb != TIPC_CONS) {
continue; printk("\n---- Start of %s log dump ----\n\n",
printk("\n---- Start of dump,%s log ----\n\n", (pb == TIPC_LOG) ? "global" : "local");
(pb == TIPC_LOG) ? "global" : "local"); printbuf_dump(pb);
printbuf_dump(pb); tipc_printbuf_reset(pb);
tipc_printbuf_reset(pb); printk("\n---- End of dump ----\n");
printk("\n-------- End of dump --------\n"); }
pb_next = pb->next;
pb->next = NULL;
pb = pb_next;
} }
spin_unlock_bh(&print_lock); spin_unlock_bh(&print_lock);
} }
@ -324,7 +364,8 @@ void tipc_log_stop(void)
} }
/** /**
* tipc_log_reinit - set TIPC log print buffer to specified size * tipc_log_reinit - (re)initialize TIPC log print buffer
* @log_size: print buffer size to use
*/ */
void tipc_log_reinit(int log_size) void tipc_log_reinit(int log_size)
@ -332,10 +373,11 @@ void tipc_log_reinit(int log_size)
tipc_log_stop(); tipc_log_stop();
if (log_size) { if (log_size) {
if (log_size <= MAX_STRING) if (log_size < TIPC_PB_MIN_SIZE)
log_size = MAX_STRING + 1; log_size = TIPC_PB_MIN_SIZE;
spin_lock_bh(&print_lock); spin_lock_bh(&print_lock);
tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC), log_size); tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC),
log_size);
spin_unlock_bh(&print_lock); spin_unlock_bh(&print_lock);
} }
} }

View File

@ -2,7 +2,7 @@
* net/tipc/dbg.h: Include file for TIPC print buffer routines * net/tipc/dbg.h: Include file for TIPC print buffer routines
* *
* Copyright (c) 1997-2006, Ericsson AB * Copyright (c) 1997-2006, Ericsson AB
* Copyright (c) 2005, Wind River Systems * Copyright (c) 2005-2006, Wind River Systems
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -37,6 +37,14 @@
#ifndef _TIPC_DBG_H #ifndef _TIPC_DBG_H
#define _TIPC_DBG_H #define _TIPC_DBG_H
/**
* struct print_buf - TIPC print buffer structure
* @buf: pointer to character array containing print buffer contents
* @size: size of character array
* @crs: pointer to first unused space in character array (i.e. final NUL)
* @next: used to link print buffers when printing to more than one at a time
*/
struct print_buf { struct print_buf {
char *buf; char *buf;
u32 size; u32 size;
@ -44,7 +52,10 @@ struct print_buf {
struct print_buf *next; struct print_buf *next;
}; };
void tipc_printbuf_init(struct print_buf *pb, char *buf, u32 sz); #define TIPC_PB_MIN_SIZE 64 /* minimum size for a print buffer's array */
#define TIPC_PB_MAX_STR 512 /* max printable string (with trailing NUL) */
void tipc_printbuf_init(struct print_buf *pb, char *buf, u32 size);
void tipc_printbuf_reset(struct print_buf *pb); void tipc_printbuf_reset(struct print_buf *pb);
int tipc_printbuf_empty(struct print_buf *pb); int tipc_printbuf_empty(struct print_buf *pb);
int tipc_printbuf_validate(struct print_buf *pb); int tipc_printbuf_validate(struct print_buf *pb);

View File

@ -131,6 +131,28 @@ static struct sk_buff *tipc_disc_init_msg(u32 type,
return buf; return buf;
} }
/**
* disc_dupl_alert - issue node address duplication alert
* @b_ptr: pointer to bearer detecting duplication
* @node_addr: duplicated node address
* @media_addr: media address advertised by duplicated node
*/
static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr,
struct tipc_media_addr *media_addr)
{
char node_addr_str[16];
char media_addr_str[64];
struct print_buf pb;
addr_string_fill(node_addr_str, node_addr);
tipc_printbuf_init(&pb, media_addr_str, sizeof(media_addr_str));
tipc_media_addr_printf(&pb, media_addr);
tipc_printbuf_validate(&pb);
warn("Duplicate %s using %s seen on <%s>\n",
node_addr_str, media_addr_str, b_ptr->publ.name);
}
/** /**
* tipc_disc_recv_msg - handle incoming link setup message (request or response) * tipc_disc_recv_msg - handle incoming link setup message (request or response)
* @buf: buffer containing message * @buf: buffer containing message
@ -157,8 +179,11 @@ void tipc_disc_recv_msg(struct sk_buff *buf)
return; return;
if (!tipc_addr_node_valid(orig)) if (!tipc_addr_node_valid(orig))
return; return;
if (orig == tipc_own_addr) if (orig == tipc_own_addr) {
if (memcmp(&media_addr, &b_ptr->publ.addr, sizeof(media_addr)))
disc_dupl_alert(b_ptr, tipc_own_addr, &media_addr);
return; return;
}
if (!in_scope(dest, tipc_own_addr)) if (!in_scope(dest, tipc_own_addr))
return; return;
if (is_slave(tipc_own_addr) && is_slave(orig)) if (is_slave(tipc_own_addr) && is_slave(orig))
@ -170,7 +195,8 @@ void tipc_disc_recv_msg(struct sk_buff *buf)
struct sk_buff *rbuf; struct sk_buff *rbuf;
struct tipc_media_addr *addr; struct tipc_media_addr *addr;
struct node *n_ptr = tipc_node_find(orig); struct node *n_ptr = tipc_node_find(orig);
int link_up; int link_fully_up;
dbg(" in own cluster\n"); dbg(" in own cluster\n");
if (n_ptr == NULL) { if (n_ptr == NULL) {
n_ptr = tipc_node_create(orig); n_ptr = tipc_node_create(orig);
@ -190,14 +216,19 @@ void tipc_disc_recv_msg(struct sk_buff *buf)
} }
addr = &link->media_addr; addr = &link->media_addr;
if (memcmp(addr, &media_addr, sizeof(*addr))) { if (memcmp(addr, &media_addr, sizeof(*addr))) {
if (tipc_link_is_up(link) || (!link->started)) {
disc_dupl_alert(b_ptr, orig, &media_addr);
spin_unlock_bh(&n_ptr->lock);
return;
}
warn("Resetting link <%s>, peer interface address changed\n", warn("Resetting link <%s>, peer interface address changed\n",
link->name); link->name);
memcpy(addr, &media_addr, sizeof(*addr)); memcpy(addr, &media_addr, sizeof(*addr));
tipc_link_reset(link); tipc_link_reset(link);
} }
link_up = tipc_link_is_up(link); link_fully_up = (link->state == WORKING_WORKING);
spin_unlock_bh(&n_ptr->lock); spin_unlock_bh(&n_ptr->lock);
if ((type == DSC_RESP_MSG) || link_up) if ((type == DSC_RESP_MSG) || link_fully_up)
return; return;
rbuf = tipc_disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr); rbuf = tipc_disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr);
if (rbuf != NULL) { if (rbuf != NULL) {

View File

@ -132,7 +132,7 @@ static void link_print(struct link *l_ptr, struct print_buf *buf,
* allow the output from multiple links to be intermixed. For this reason * allow the output from multiple links to be intermixed. For this reason
* routines of the form "dbg_link_XXX()" have been created that will capture * routines of the form "dbg_link_XXX()" have been created that will capture
* debug info into a link's personal print buffer, which can then be dumped * debug info into a link's personal print buffer, which can then be dumped
* into the TIPC system log (LOG) upon request. * into the TIPC system log (TIPC_LOG) upon request.
* *
* To enable per-link debugging, use LINK_LOG_BUF_SIZE to specify the size * To enable per-link debugging, use LINK_LOG_BUF_SIZE to specify the size
* of the print buffer used by each link. If LINK_LOG_BUF_SIZE is set to 0, * of the print buffer used by each link. If LINK_LOG_BUF_SIZE is set to 0,
@ -141,7 +141,7 @@ static void link_print(struct link *l_ptr, struct print_buf *buf,
* when there is only a single link in the system being debugged. * when there is only a single link in the system being debugged.
* *
* Notes: * Notes:
* - When enabled, LINK_LOG_BUF_SIZE should be set to at least 1000 (bytes) * - When enabled, LINK_LOG_BUF_SIZE should be set to at least TIPC_PB_MIN_SIZE
* - "l_ptr" must be valid when using dbg_link_XXX() macros * - "l_ptr" must be valid when using dbg_link_XXX() macros
*/ */
@ -159,13 +159,13 @@ static void link_print(struct link *l_ptr, struct print_buf *buf,
static void dbg_print_link(struct link *l_ptr, const char *str) static void dbg_print_link(struct link *l_ptr, const char *str)
{ {
if (DBG_OUTPUT) if (DBG_OUTPUT != TIPC_NULL)
link_print(l_ptr, DBG_OUTPUT, str); link_print(l_ptr, DBG_OUTPUT, str);
} }
static void dbg_print_buf_chain(struct sk_buff *root_buf) static void dbg_print_buf_chain(struct sk_buff *root_buf)
{ {
if (DBG_OUTPUT) { if (DBG_OUTPUT != TIPC_NULL) {
struct sk_buff *buf = root_buf; struct sk_buff *buf = root_buf;
while (buf) { while (buf) {

View File

@ -122,7 +122,7 @@ void tipc_named_publish(struct publication *publ)
struct sk_buff *buf; struct sk_buff *buf;
struct distr_item *item; struct distr_item *item;
list_add(&publ->local_list, &publ_root); list_add_tail(&publ->local_list, &publ_root);
publ_cnt++; publ_cnt++;
buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0); buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0);

View File

@ -648,7 +648,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (network address)"); " (network address)");
if (!tipc_nodes) if (tipc_mode != TIPC_NET_MODE)
return tipc_cfg_reply_none(); return tipc_cfg_reply_none();
/* Get space for all unicast links + multicast link */ /* Get space for all unicast links + multicast link */

View File

@ -505,9 +505,14 @@ static void port_timeout(unsigned long ref)
struct port *p_ptr = tipc_port_lock(ref); struct port *p_ptr = tipc_port_lock(ref);
struct sk_buff *buf = NULL; struct sk_buff *buf = NULL;
if (!p_ptr || !p_ptr->publ.connected) if (!p_ptr)
return; return;
if (!p_ptr->publ.connected) {
tipc_port_unlock(p_ptr);
return;
}
/* Last probe answered ? */ /* Last probe answered ? */
if (p_ptr->probing_state == PROBING) { if (p_ptr->probing_state == PROBING) {
buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT); buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT);

View File

@ -2,7 +2,7 @@
* net/tipc/socket.c: TIPC socket API * net/tipc/socket.c: TIPC socket API
* *
* Copyright (c) 2001-2006, Ericsson AB * Copyright (c) 2001-2006, Ericsson AB
* Copyright (c) 2004-2005, Wind River Systems * Copyright (c) 2004-2006, Wind River Systems
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -629,6 +629,9 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
return -ENOTCONN; return -ENOTCONN;
} }
if (unlikely(m->msg_name))
return -EISCONN;
/* /*
* Send each iovec entry using one or more messages * Send each iovec entry using one or more messages
* *
@ -641,6 +644,8 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
curr_iovlen = m->msg_iovlen; curr_iovlen = m->msg_iovlen;
my_msg.msg_iov = &my_iov; my_msg.msg_iov = &my_iov;
my_msg.msg_iovlen = 1; my_msg.msg_iovlen = 1;
my_msg.msg_flags = m->msg_flags;
my_msg.msg_name = NULL;
bytes_sent = 0; bytes_sent = 0;
while (curr_iovlen--) { while (curr_iovlen--) {
@ -1203,7 +1208,8 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
atomic_inc(&tipc_queue_size); atomic_inc(&tipc_queue_size);
skb_queue_tail(&sock->sk->sk_receive_queue, buf); skb_queue_tail(&sock->sk->sk_receive_queue, buf);
wake_up_interruptible(sock->sk->sk_sleep); if (waitqueue_active(sock->sk->sk_sleep))
wake_up_interruptible(sock->sk->sk_sleep);
return TIPC_OK; return TIPC_OK;
} }
@ -1218,7 +1224,8 @@ static void wakeupdispatch(struct tipc_port *tport)
{ {
struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle; struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle;
wake_up_interruptible(tsock->sk.sk_sleep); if (waitqueue_active(tsock->sk.sk_sleep))
wake_up_interruptible(tsock->sk.sk_sleep);
} }
/** /**

View File

@ -155,7 +155,7 @@ void tipc_subscr_report_overlap(struct subscription *sub,
sub->seq.upper, found_lower, found_upper); sub->seq.upper, found_lower, found_upper);
if (!tipc_subscr_overlap(sub, found_lower, found_upper)) if (!tipc_subscr_overlap(sub, found_lower, found_upper))
return; return;
if (!must && (sub->filter != TIPC_SUB_PORTS)) if (!must && !(sub->filter & TIPC_SUB_PORTS))
return; return;
subscr_send_event(sub, found_lower, found_upper, event, port_ref, node); subscr_send_event(sub, found_lower, found_upper, event, port_ref, node);
} }
@ -176,6 +176,13 @@ static void subscr_timeout(struct subscription *sub)
if (subscriber == NULL) if (subscriber == NULL)
return; return;
/* Validate timeout (in case subscription is being cancelled) */
if (sub->timeout == TIPC_WAIT_FOREVER) {
tipc_ref_unlock(subscriber_ref);
return;
}
/* Unlink subscription from name table */ /* Unlink subscription from name table */
tipc_nametbl_unsubscribe(sub); tipc_nametbl_unsubscribe(sub);
@ -198,6 +205,20 @@ static void subscr_timeout(struct subscription *sub)
atomic_dec(&topsrv.subscription_count); atomic_dec(&topsrv.subscription_count);
} }
/**
* subscr_del - delete a subscription within a subscription list
*
* Called with subscriber locked.
*/
static void subscr_del(struct subscription *sub)
{
tipc_nametbl_unsubscribe(sub);
list_del(&sub->subscription_list);
kfree(sub);
atomic_dec(&topsrv.subscription_count);
}
/** /**
* subscr_terminate - terminate communication with a subscriber * subscr_terminate - terminate communication with a subscriber
* *
@ -227,12 +248,9 @@ static void subscr_terminate(struct subscriber *subscriber)
k_cancel_timer(&sub->timer); k_cancel_timer(&sub->timer);
k_term_timer(&sub->timer); k_term_timer(&sub->timer);
} }
tipc_nametbl_unsubscribe(sub); dbg("Term: Removing sub %u,%u,%u from subscriber %x list\n",
list_del(&sub->subscription_list);
dbg("Term: Removed sub %u,%u,%u from subscriber %x list\n",
sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber);
kfree(sub); subscr_del(sub);
atomic_dec(&topsrv.subscription_count);
} }
/* Sever connection to subscriber */ /* Sever connection to subscriber */
@ -252,6 +270,49 @@ static void subscr_terminate(struct subscriber *subscriber)
kfree(subscriber); kfree(subscriber);
} }
/**
* subscr_cancel - handle subscription cancellation request
*
* Called with subscriber locked. Routine must temporarily release this lock
* to enable the subscription timeout routine to finish without deadlocking;
* the lock is then reclaimed to allow caller to release it upon return.
*
* Note that fields of 's' use subscriber's endianness!
*/
static void subscr_cancel(struct tipc_subscr *s,
struct subscriber *subscriber)
{
struct subscription *sub;
struct subscription *sub_temp;
int found = 0;
/* Find first matching subscription, exit if not found */
list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list,
subscription_list) {
if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) {
found = 1;
break;
}
}
if (!found)
return;
/* Cancel subscription timer (if used), then delete subscription */
if (sub->timeout != TIPC_WAIT_FOREVER) {
sub->timeout = TIPC_WAIT_FOREVER;
spin_unlock_bh(subscriber->lock);
k_cancel_timer(&sub->timer);
k_term_timer(&sub->timer);
spin_lock_bh(subscriber->lock);
}
dbg("Cancel: removing sub %u,%u,%u from subscriber %x list\n",
sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber);
subscr_del(sub);
}
/** /**
* subscr_subscribe - create subscription for subscriber * subscr_subscribe - create subscription for subscriber
* *
@ -263,6 +324,21 @@ static void subscr_subscribe(struct tipc_subscr *s,
{ {
struct subscription *sub; struct subscription *sub;
/* Determine/update subscriber's endianness */
if (s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE))
subscriber->swap = 0;
else
subscriber->swap = 1;
/* Detect & process a subscription cancellation request */
if (s->filter & htohl(TIPC_SUB_CANCEL, subscriber->swap)) {
s->filter &= ~htohl(TIPC_SUB_CANCEL, subscriber->swap);
subscr_cancel(s, subscriber);
return;
}
/* Refuse subscription if global limit exceeded */ /* Refuse subscription if global limit exceeded */
if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) { if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) {
@ -281,13 +357,6 @@ static void subscr_subscribe(struct tipc_subscr *s,
return; return;
} }
/* Determine/update subscriber's endianness */
if ((s->filter == TIPC_SUB_PORTS) || (s->filter == TIPC_SUB_SERVICE))
subscriber->swap = 0;
else
subscriber->swap = 1;
/* Initialize subscription object */ /* Initialize subscription object */
memset(sub, 0, sizeof(*sub)); memset(sub, 0, sizeof(*sub));
@ -296,8 +365,8 @@ static void subscr_subscribe(struct tipc_subscr *s,
sub->seq.upper = htohl(s->seq.upper, subscriber->swap); sub->seq.upper = htohl(s->seq.upper, subscriber->swap);
sub->timeout = htohl(s->timeout, subscriber->swap); sub->timeout = htohl(s->timeout, subscriber->swap);
sub->filter = htohl(s->filter, subscriber->swap); sub->filter = htohl(s->filter, subscriber->swap);
if ((((sub->filter != TIPC_SUB_PORTS) if ((!(sub->filter & TIPC_SUB_PORTS)
&& (sub->filter != TIPC_SUB_SERVICE))) == !(sub->filter & TIPC_SUB_SERVICE))
|| (sub->seq.lower > sub->seq.upper)) { || (sub->seq.lower > sub->seq.upper)) {
warn("Subscription rejected, illegal request\n"); warn("Subscription rejected, illegal request\n");
kfree(sub); kfree(sub);