diff options
| author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-20 13:27:38 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-20 13:27:38 -0400 |
| commit | c1448791648d44ecbf8cadb192704e3e6eb3bb0e (patch) | |
| tree | 606cb5289bc8770e925761c6e1617eb44a6dafef | |
| parent | ac4e0aba7daf0a7c6ac20974070428481dc940f5 (diff) | |
| parent | 7b19ffc40b0247fcfe083644fdb621fdb3c05ef6 (diff) | |
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().
...
34 files changed, 398 insertions, 188 deletions
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index e7c800f4c3ad..07eafbc5dc3a 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c | |||
| @@ -711,6 +711,7 @@ static void dtl1_release(struct pcmcia_device *link) | |||
| 711 | 711 | ||
| 712 | static struct pcmcia_device_id dtl1_ids[] = { | 712 | static struct pcmcia_device_id dtl1_ids[] = { |
| 713 | PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d), | 713 | PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d), |
| 714 | PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-4", 0xe1bfdd64, 0x9102bc82), | ||
| 714 | PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863), | 715 | PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863), |
| 715 | PCMCIA_DEVICE_PROD_ID12("Socket", "CF+ Personal Network Card", 0xb38bcc2e, 0xe732bae3), | 716 | PCMCIA_DEVICE_PROD_ID12("Socket", "CF+ Personal Network Card", 0xb38bcc2e, 0xe732bae3), |
| 716 | PCMCIA_DEVICE_NULL | 717 | PCMCIA_DEVICE_NULL |
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index 7565642a007a..fdea58ae16b2 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c | |||
| @@ -118,6 +118,9 @@ static struct usb_device_id blacklist_ids[] = { | |||
| 118 | /* IBM/Lenovo ThinkPad with Broadcom chip */ | 118 | /* IBM/Lenovo ThinkPad with Broadcom chip */ |
| 119 | { USB_DEVICE(0x0a5c, 0x201e), .driver_info = HCI_WRONG_SCO_MTU }, | 119 | { USB_DEVICE(0x0a5c, 0x201e), .driver_info = HCI_WRONG_SCO_MTU }, |
| 120 | 120 | ||
| 121 | /* ANYCOM Bluetooth USB-200 and USB-250 */ | ||
| 122 | { USB_DEVICE(0x0a5c, 0x2111), .driver_info = HCI_RESET }, | ||
| 123 | |||
| 121 | /* Microsoft Wireless Transceiver for Bluetooth 2.0 */ | 124 | /* Microsoft Wireless Transceiver for Bluetooth 2.0 */ |
| 122 | { USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET }, | 125 | { USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET }, |
| 123 | 126 | ||
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 4178b4b1d2df..82c10dec1b5a 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c | |||
| @@ -58,7 +58,11 @@ | |||
| 58 | #include <linux/tcp.h> | 58 | #include <linux/tcp.h> |
| 59 | #include <linux/percpu.h> | 59 | #include <linux/percpu.h> |
| 60 | 60 | ||
| 61 | static DEFINE_PER_CPU(struct net_device_stats, loopback_stats); | 61 | struct pcpu_lstats { |
| 62 | unsigned long packets; | ||
| 63 | unsigned long bytes; | ||
| 64 | }; | ||
| 65 | static DEFINE_PER_CPU(struct pcpu_lstats, pcpu_lstats); | ||
| 62 | 66 | ||
| 63 | #define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16) | 67 | #define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16) |
| 64 | 68 | ||
| @@ -128,7 +132,7 @@ static void emulate_large_send_offload(struct sk_buff *skb) | |||
| 128 | */ | 132 | */ |
| 129 | static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) | 133 | static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) |
| 130 | { | 134 | { |
| 131 | struct net_device_stats *lb_stats; | 135 | struct pcpu_lstats *lb_stats; |
| 132 | 136 | ||
| 133 | skb_orphan(skb); | 137 | skb_orphan(skb); |
| 134 | 138 | ||
| @@ -149,16 +153,14 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 149 | #endif | 153 | #endif |
| 150 | dev->last_rx = jiffies; | 154 | dev->last_rx = jiffies; |
| 151 | 155 | ||
| 152 | lb_stats = &per_cpu(loopback_stats, get_cpu()); | 156 | /* it's OK to use __get_cpu_var() because BHs are off */ |
| 153 | lb_stats->rx_bytes += skb->len; | 157 | lb_stats = &__get_cpu_var(pcpu_lstats); |
| 154 | lb_stats->tx_bytes = lb_stats->rx_bytes; | 158 | lb_stats->bytes += skb->len; |
| 155 | lb_stats->rx_packets++; | 159 | lb_stats->packets++; |
| 156 | lb_stats->tx_packets = lb_stats->rx_packets; | ||
| 157 | put_cpu(); | ||
| 158 | 160 | ||
| 159 | netif_rx(skb); | 161 | netif_rx(skb); |
| 160 | 162 | ||
| 161 | return(0); | 163 | return 0; |
| 162 | } | 164 | } |
| 163 | 165 | ||
| 164 | static struct net_device_stats loopback_stats; | 166 | static struct net_device_stats loopback_stats; |
| @@ -166,20 +168,21 @@ static struct net_device_stats loopback_stats; | |||
| 166 | static struct net_device_stats *get_stats(struct net_device *dev) | 168 | static struct net_device_stats *get_stats(struct net_device *dev) |
| 167 | { | 169 | { |
| 168 | struct net_device_stats *stats = &loopback_stats; | 170 | struct net_device_stats *stats = &loopback_stats; |
| 171 | unsigned long bytes = 0; | ||
| 172 | unsigned long packets = 0; | ||
| 169 | int i; | 173 | int i; |
| 170 | 174 | ||
| 171 | memset(stats, 0, sizeof(struct net_device_stats)); | ||
| 172 | |||
| 173 | for_each_possible_cpu(i) { | 175 | for_each_possible_cpu(i) { |
| 174 | struct net_device_stats *lb_stats; | 176 | const struct pcpu_lstats *lb_stats; |
| 175 | 177 | ||
| 176 | lb_stats = &per_cpu(loopback_stats, i); | 178 | lb_stats = &per_cpu(pcpu_lstats, i); |
| 177 | stats->rx_bytes += lb_stats->rx_bytes; | 179 | bytes += lb_stats->bytes; |
| 178 | stats->tx_bytes += lb_stats->tx_bytes; | 180 | packets += lb_stats->packets; |
| 179 | stats->rx_packets += lb_stats->rx_packets; | ||
| 180 | stats->tx_packets += lb_stats->tx_packets; | ||
| 181 | } | 181 | } |
| 182 | 182 | stats->rx_packets = packets; | |
| 183 | stats->tx_packets = packets; | ||
| 184 | stats->rx_bytes = bytes; | ||
| 185 | stats->tx_bytes = bytes; | ||
| 183 | return stats; | 186 | return stats; |
| 184 | } | 187 | } |
| 185 | 188 | ||
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 327836b1014e..8e398499c045 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
| @@ -68,8 +68,8 @@ | |||
| 68 | 68 | ||
| 69 | #define DRV_MODULE_NAME "tg3" | 69 | #define DRV_MODULE_NAME "tg3" |
| 70 | #define PFX DRV_MODULE_NAME ": " | 70 | #define PFX DRV_MODULE_NAME ": " |
| 71 | #define DRV_MODULE_VERSION "3.66" | 71 | #define DRV_MODULE_VERSION "3.67" |
| 72 | #define DRV_MODULE_RELDATE "September 23, 2006" | 72 | #define DRV_MODULE_RELDATE "October 18, 2006" |
| 73 | 73 | ||
| 74 | #define TG3_DEF_MAC_MODE 0 | 74 | #define TG3_DEF_MAC_MODE 0 |
| 75 | #define TG3_DEF_RX_MODE 0 | 75 | #define TG3_DEF_RX_MODE 0 |
| @@ -129,7 +129,7 @@ | |||
| 129 | #define RX_JUMBO_PKT_BUF_SZ (9046 + tp->rx_offset + 64) | 129 | #define RX_JUMBO_PKT_BUF_SZ (9046 + tp->rx_offset + 64) |
| 130 | 130 | ||
| 131 | /* minimum number of free TX descriptors required to wake up TX process */ | 131 | /* minimum number of free TX descriptors required to wake up TX process */ |
| 132 | #define TG3_TX_WAKEUP_THRESH (TG3_TX_RING_SIZE / 4) | 132 | #define TG3_TX_WAKEUP_THRESH(tp) ((tp)->tx_pending / 4) |
| 133 | 133 | ||
| 134 | /* number of ETHTOOL_GSTATS u64's */ | 134 | /* number of ETHTOOL_GSTATS u64's */ |
| 135 | #define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64)) | 135 | #define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64)) |
| @@ -3075,10 +3075,10 @@ static void tg3_tx(struct tg3 *tp) | |||
| 3075 | smp_mb(); | 3075 | smp_mb(); |
| 3076 | 3076 | ||
| 3077 | if (unlikely(netif_queue_stopped(tp->dev) && | 3077 | if (unlikely(netif_queue_stopped(tp->dev) && |
| 3078 | (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH))) { | 3078 | (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)))) { |
| 3079 | netif_tx_lock(tp->dev); | 3079 | netif_tx_lock(tp->dev); |
| 3080 | if (netif_queue_stopped(tp->dev) && | 3080 | if (netif_queue_stopped(tp->dev) && |
| 3081 | (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH)) | 3081 | (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp))) |
| 3082 | netif_wake_queue(tp->dev); | 3082 | netif_wake_queue(tp->dev); |
| 3083 | netif_tx_unlock(tp->dev); | 3083 | netif_tx_unlock(tp->dev); |
| 3084 | } | 3084 | } |
| @@ -3928,7 +3928,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 3928 | tp->tx_prod = entry; | 3928 | tp->tx_prod = entry; |
| 3929 | if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) { | 3929 | if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) { |
| 3930 | netif_stop_queue(dev); | 3930 | netif_stop_queue(dev); |
| 3931 | if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH) | 3931 | if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)) |
| 3932 | netif_wake_queue(tp->dev); | 3932 | netif_wake_queue(tp->dev); |
| 3933 | } | 3933 | } |
| 3934 | 3934 | ||
| @@ -4143,7 +4143,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) | |||
| 4143 | tp->tx_prod = entry; | 4143 | tp->tx_prod = entry; |
| 4144 | if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) { | 4144 | if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) { |
| 4145 | netif_stop_queue(dev); | 4145 | netif_stop_queue(dev); |
| 4146 | if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH) | 4146 | if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)) |
| 4147 | netif_wake_queue(tp->dev); | 4147 | netif_wake_queue(tp->dev); |
| 4148 | } | 4148 | } |
| 4149 | 4149 | ||
| @@ -8106,7 +8106,10 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e | |||
| 8106 | 8106 | ||
| 8107 | if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) || | 8107 | if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) || |
| 8108 | (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) || | 8108 | (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) || |
| 8109 | (ering->tx_pending > TG3_TX_RING_SIZE - 1)) | 8109 | (ering->tx_pending > TG3_TX_RING_SIZE - 1) || |
| 8110 | (ering->tx_pending <= MAX_SKB_FRAGS) || | ||
| 8111 | ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_1_BUG) && | ||
| 8112 | (ering->tx_pending <= (MAX_SKB_FRAGS * 3)))) | ||
| 8110 | return -EINVAL; | 8113 | return -EINVAL; |
| 8111 | 8114 | ||
| 8112 | if (netif_running(dev)) { | 8115 | if (netif_running(dev)) { |
diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 0e058a2d1c6d..2d36f6db3706 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h | |||
| @@ -342,6 +342,8 @@ struct tcp_sock { | |||
| 342 | 342 | ||
| 343 | unsigned long last_synq_overflow; | 343 | unsigned long last_synq_overflow; |
| 344 | 344 | ||
| 345 | __u32 tso_deferred; | ||
| 346 | |||
| 345 | /* Receiver side RTT estimation */ | 347 | /* Receiver side RTT estimation */ |
| 346 | struct { | 348 | struct { |
| 347 | __u32 rtt; | 349 | __u32 rtt; |
diff --git a/include/linux/tipc.h b/include/linux/tipc.h index 243a15f54002..bea469455a0c 100644 --- a/include/linux/tipc.h +++ b/include/linux/tipc.h | |||
| @@ -129,6 +129,7 @@ static inline unsigned int tipc_node(__u32 addr) | |||
| 129 | 129 | ||
| 130 | #define TIPC_SUB_PORTS 0x01 /* filter for port availability */ | 130 | #define TIPC_SUB_PORTS 0x01 /* filter for port availability */ |
| 131 | #define TIPC_SUB_SERVICE 0x02 /* filter for service availability */ | 131 | #define TIPC_SUB_SERVICE 0x02 /* filter for service availability */ |
| 132 | #define TIPC_SUB_CANCEL 0x04 /* cancel a subscription */ | ||
| 132 | #if 0 | 133 | #if 0 |
| 133 | /* The following filter options are not currently implemented */ | 134 | /* The following filter options are not currently implemented */ |
| 134 | #define TIPC_SUB_NO_BIND_EVTS 0x04 /* filter out "publish" events */ | 135 | #define TIPC_SUB_NO_BIND_EVTS 0x04 /* filter out "publish" events */ |
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h index f13cc0c2b163..aa10a8178e70 100644 --- a/include/net/inetpeer.h +++ b/include/net/inetpeer.h | |||
| @@ -17,14 +17,15 @@ | |||
| 17 | 17 | ||
| 18 | struct inet_peer | 18 | struct inet_peer |
| 19 | { | 19 | { |
| 20 | /* group together avl_left,avl_right,v4daddr to speedup lookups */ | ||
| 20 | struct inet_peer *avl_left, *avl_right; | 21 | struct inet_peer *avl_left, *avl_right; |
| 22 | __be32 v4daddr; /* peer's address */ | ||
| 23 | __u16 avl_height; | ||
| 24 | __u16 ip_id_count; /* IP ID for the next packet */ | ||
| 21 | struct inet_peer *unused_next, **unused_prevp; | 25 | struct inet_peer *unused_next, **unused_prevp; |
| 22 | __u32 dtime; /* the time of last use of not | 26 | __u32 dtime; /* the time of last use of not |
| 23 | * referenced entries */ | 27 | * referenced entries */ |
| 24 | atomic_t refcnt; | 28 | atomic_t refcnt; |
| 25 | __be32 v4daddr; /* peer's address */ | ||
| 26 | __u16 avl_height; | ||
| 27 | __u16 ip_id_count; /* IP ID for the next packet */ | ||
| 28 | atomic_t rid; /* Frag reception counter */ | 29 | atomic_t rid; /* Frag reception counter */ |
| 29 | __u32 tcp_ts; | 30 | __u32 tcp_ts; |
| 30 | unsigned long tcp_ts_stamp; | 31 | unsigned long tcp_ts_stamp; |
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 6ca6b71dfe0f..c14b70ed4c57 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h | |||
| @@ -36,13 +36,6 @@ struct route_info { | |||
| 36 | #define RT6_LOOKUP_F_REACHABLE 0x2 | 36 | #define RT6_LOOKUP_F_REACHABLE 0x2 |
| 37 | #define RT6_LOOKUP_F_HAS_SADDR 0x4 | 37 | #define RT6_LOOKUP_F_HAS_SADDR 0x4 |
| 38 | 38 | ||
| 39 | struct pol_chain { | ||
| 40 | int type; | ||
| 41 | int priority; | ||
| 42 | struct fib6_node *rules; | ||
| 43 | struct pol_chain *next; | ||
| 44 | }; | ||
| 45 | |||
| 46 | extern struct rt6_info ip6_null_entry; | 39 | extern struct rt6_info ip6_null_entry; |
| 47 | 40 | ||
| 48 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 41 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 82229146bac7..949b932d2f08 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h | |||
| @@ -21,17 +21,14 @@ | |||
| 21 | #include <net/fib_rules.h> | 21 | #include <net/fib_rules.h> |
| 22 | 22 | ||
| 23 | struct fib_config { | 23 | struct fib_config { |
| 24 | u8 fc_family; | ||
| 25 | u8 fc_dst_len; | 24 | u8 fc_dst_len; |
| 26 | u8 fc_src_len; | ||
| 27 | u8 fc_tos; | 25 | u8 fc_tos; |
| 28 | u8 fc_protocol; | 26 | u8 fc_protocol; |
| 29 | u8 fc_scope; | 27 | u8 fc_scope; |
| 30 | u8 fc_type; | 28 | u8 fc_type; |
| 31 | /* 1 byte unused */ | 29 | /* 3 bytes unused */ |
| 32 | u32 fc_table; | 30 | u32 fc_table; |
| 33 | __be32 fc_dst; | 31 | __be32 fc_dst; |
| 34 | __be32 fc_src; | ||
| 35 | __be32 fc_gw; | 32 | __be32 fc_gw; |
| 36 | int fc_oif; | 33 | int fc_oif; |
| 37 | u32 fc_flags; | 34 | u32 fc_flags; |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 9a562cf7406b..66782010f82c 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
| @@ -507,12 +507,10 @@ static int hidp_session(void *arg) | |||
| 507 | 507 | ||
| 508 | hidp_del_timer(session); | 508 | hidp_del_timer(session); |
| 509 | 509 | ||
| 510 | if (intr_sk->sk_state != BT_CONNECTED) | ||
| 511 | wait_event_timeout(*(ctrl_sk->sk_sleep), (ctrl_sk->sk_state == BT_CLOSED), HZ); | ||
| 512 | |||
| 513 | fput(session->intr_sock->file); | 510 | fput(session->intr_sock->file); |
| 514 | 511 | ||
| 515 | wait_event_timeout(*(intr_sk->sk_sleep), (intr_sk->sk_state == BT_CLOSED), HZ); | 512 | wait_event_timeout(*(ctrl_sk->sk_sleep), |
| 513 | (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500)); | ||
| 516 | 514 | ||
| 517 | fput(session->ctrl_sock->file); | 515 | fput(session->ctrl_sock->file); |
| 518 | 516 | ||
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index ead5920c26d6..9308af060b44 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
| @@ -335,13 +335,13 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len) | |||
| 335 | memcpy(skb->data, msg, len); | 335 | memcpy(skb->data, msg, len); |
| 336 | skb->len += len; | 336 | skb->len += len; |
| 337 | 337 | ||
| 338 | udph = (struct udphdr *) skb_push(skb, sizeof(*udph)); | 338 | skb->h.uh = udph = (struct udphdr *) skb_push(skb, sizeof(*udph)); |
| 339 | udph->source = htons(np->local_port); | 339 | udph->source = htons(np->local_port); |
| 340 | udph->dest = htons(np->remote_port); | 340 | udph->dest = htons(np->remote_port); |
| 341 | udph->len = htons(udp_len); | 341 | udph->len = htons(udp_len); |
| 342 | udph->check = 0; | 342 | udph->check = 0; |
| 343 | 343 | ||
| 344 | iph = (struct iphdr *)skb_push(skb, sizeof(*iph)); | 344 | skb->nh.iph = iph = (struct iphdr *)skb_push(skb, sizeof(*iph)); |
| 345 | 345 | ||
| 346 | /* iph->version = 4; iph->ihl = 5; */ | 346 | /* iph->version = 4; iph->ihl = 5; */ |
| 347 | put_unaligned(0x45, (unsigned char *)iph); | 347 | put_unaligned(0x45, (unsigned char *)iph); |
| @@ -357,8 +357,8 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len) | |||
| 357 | iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); | 357 | iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); |
| 358 | 358 | ||
| 359 | eth = (struct ethhdr *) skb_push(skb, ETH_HLEN); | 359 | eth = (struct ethhdr *) skb_push(skb, ETH_HLEN); |
| 360 | 360 | skb->mac.raw = skb->data; | |
| 361 | eth->h_proto = htons(ETH_P_IP); | 361 | skb->protocol = eth->h_proto = htons(ETH_P_IP); |
| 362 | memcpy(eth->h_source, np->local_mac, 6); | 362 | memcpy(eth->h_source, np->local_mac, 6); |
| 363 | memcpy(eth->h_dest, np->remote_mac, 6); | 363 | memcpy(eth->h_dest, np->remote_mac, 6); |
| 364 | 364 | ||
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 491429ce9394..23489f7232d2 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c | |||
| @@ -1275,7 +1275,6 @@ static int dn_route_input_slow(struct sk_buff *skb) | |||
| 1275 | goto e_inval; | 1275 | goto e_inval; |
| 1276 | 1276 | ||
| 1277 | res.type = RTN_LOCAL; | 1277 | res.type = RTN_LOCAL; |
| 1278 | flags |= RTCF_DIRECTSRC; | ||
| 1279 | } else { | 1278 | } else { |
| 1280 | __le16 src_map = fl.fld_src; | 1279 | __le16 src_map = fl.fld_src; |
| 1281 | free_res = 1; | 1280 | free_res = 1; |
| @@ -1346,7 +1345,7 @@ static int dn_route_input_slow(struct sk_buff *skb) | |||
| 1346 | goto make_route; | 1345 | goto make_route; |
| 1347 | 1346 | ||
| 1348 | /* Packet was intra-ethernet, so we know its on-link */ | 1347 | /* Packet was intra-ethernet, so we know its on-link */ |
| 1349 | if (cb->rt_flags | DN_RT_F_IE) { | 1348 | if (cb->rt_flags & DN_RT_F_IE) { |
| 1350 | gateway = cb->src; | 1349 | gateway = cb->src; |
| 1351 | flags |= RTCF_DIRECTSRC; | 1350 | flags |= RTCF_DIRECTSRC; |
| 1352 | goto make_route; | 1351 | goto make_route; |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 9c399a70dd5d..af0190d8b6c0 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
| @@ -482,9 +482,7 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
| 482 | memset(cfg, 0, sizeof(*cfg)); | 482 | memset(cfg, 0, sizeof(*cfg)); |
| 483 | 483 | ||
| 484 | rtm = nlmsg_data(nlh); | 484 | rtm = nlmsg_data(nlh); |
| 485 | cfg->fc_family = rtm->rtm_family; | ||
| 486 | cfg->fc_dst_len = rtm->rtm_dst_len; | 485 | cfg->fc_dst_len = rtm->rtm_dst_len; |
| 487 | cfg->fc_src_len = rtm->rtm_src_len; | ||
| 488 | cfg->fc_tos = rtm->rtm_tos; | 486 | cfg->fc_tos = rtm->rtm_tos; |
| 489 | cfg->fc_table = rtm->rtm_table; | 487 | cfg->fc_table = rtm->rtm_table; |
| 490 | cfg->fc_protocol = rtm->rtm_protocol; | 488 | cfg->fc_protocol = rtm->rtm_protocol; |
| @@ -501,9 +499,6 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
| 501 | case RTA_DST: | 499 | case RTA_DST: |
| 502 | cfg->fc_dst = nla_get_be32(attr); | 500 | cfg->fc_dst = nla_get_be32(attr); |
| 503 | break; | 501 | break; |
| 504 | case RTA_SRC: | ||
| 505 | cfg->fc_src = nla_get_be32(attr); | ||
| 506 | break; | ||
| 507 | case RTA_OIF: | 502 | case RTA_OIF: |
| 508 | cfg->fc_oif = nla_get_u32(attr); | 503 | cfg->fc_oif = nla_get_u32(attr); |
| 509 | break; | 504 | break; |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 78a44b01c035..4b90927619b8 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
| @@ -1932,6 +1932,9 @@ compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
| 1932 | { | 1932 | { |
| 1933 | int ret; | 1933 | int ret; |
| 1934 | 1934 | ||
| 1935 | if (!capable(CAP_NET_ADMIN)) | ||
| 1936 | return -EPERM; | ||
| 1937 | |||
| 1935 | switch (cmd) { | 1938 | switch (cmd) { |
| 1936 | case IPT_SO_GET_INFO: | 1939 | case IPT_SO_GET_INFO: |
| 1937 | ret = get_info(user, len, 1); | 1940 | ret = get_info(user, len, 1); |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 6bbd98575172..22ef8bd26620 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
| @@ -373,7 +373,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info) | |||
| 373 | seq = ntohl(th->seq); | 373 | seq = ntohl(th->seq); |
| 374 | if (sk->sk_state != TCP_LISTEN && | 374 | if (sk->sk_state != TCP_LISTEN && |
| 375 | !between(seq, tp->snd_una, tp->snd_nxt)) { | 375 | !between(seq, tp->snd_una, tp->snd_nxt)) { |
| 376 | NET_INC_STATS(LINUX_MIB_OUTOFWINDOWICMPS); | 376 | NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS); |
| 377 | goto out; | 377 | goto out; |
| 378 | } | 378 | } |
| 379 | 379 | ||
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index f22536e32cb1..ca406157724c 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
| @@ -1096,10 +1096,14 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_ | |||
| 1096 | u32 send_win, cong_win, limit, in_flight; | 1096 | u32 send_win, cong_win, limit, in_flight; |
| 1097 | 1097 | ||
| 1098 | if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) | 1098 | if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) |
| 1099 | return 0; | 1099 | goto send_now; |
| 1100 | 1100 | ||
| 1101 | if (icsk->icsk_ca_state != TCP_CA_Open) | 1101 | if (icsk->icsk_ca_state != TCP_CA_Open) |
| 1102 | return 0; | 1102 | goto send_now; |
| 1103 | |||
| 1104 | /* Defer for less than two clock ticks. */ | ||
| 1105 | if (!tp->tso_deferred && ((jiffies<<1)>>1) - (tp->tso_deferred>>1) > 1) | ||
| 1106 | goto send_now; | ||
| 1103 | 1107 | ||
| 1104 | in_flight = tcp_packets_in_flight(tp); | 1108 | in_flight = tcp_packets_in_flight(tp); |
| 1105 | 1109 | ||
| @@ -1115,7 +1119,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_ | |||
| 1115 | 1119 | ||
| 1116 | /* If a full-sized TSO skb can be sent, do it. */ | 1120 | /* If a full-sized TSO skb can be sent, do it. */ |
| 1117 | if (limit >= 65536) | 1121 | if (limit >= 65536) |
| 1118 | return 0; | 1122 | goto send_now; |
| 1119 | 1123 | ||
| 1120 | if (sysctl_tcp_tso_win_divisor) { | 1124 | if (sysctl_tcp_tso_win_divisor) { |
| 1121 | u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache); | 1125 | 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_ | |||
| 1125 | */ | 1129 | */ |
| 1126 | chunk /= sysctl_tcp_tso_win_divisor; | 1130 | chunk /= sysctl_tcp_tso_win_divisor; |
| 1127 | if (limit >= chunk) | 1131 | if (limit >= chunk) |
| 1128 | return 0; | 1132 | goto send_now; |
| 1129 | } else { | 1133 | } else { |
| 1130 | /* Different approach, try not to defer past a single | 1134 | /* Different approach, try not to defer past a single |
| 1131 | * ACK. Receiver should ACK every other full sized | 1135 | * 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_ | |||
| 1133 | * then send now. | 1137 | * then send now. |
| 1134 | */ | 1138 | */ |
| 1135 | if (limit > tcp_max_burst(tp) * tp->mss_cache) | 1139 | if (limit > tcp_max_burst(tp) * tp->mss_cache) |
| 1136 | return 0; | 1140 | goto send_now; |
| 1137 | } | 1141 | } |
| 1138 | 1142 | ||
| 1139 | /* Ok, it looks like it is advisable to defer. */ | 1143 | /* Ok, it looks like it is advisable to defer. */ |
| 1144 | tp->tso_deferred = 1 | (jiffies<<1); | ||
| 1145 | |||
| 1140 | return 1; | 1146 | return 1; |
| 1147 | |||
| 1148 | send_now: | ||
| 1149 | tp->tso_deferred = 0; | ||
| 1150 | return 0; | ||
| 1141 | } | 1151 | } |
| 1142 | 1152 | ||
| 1143 | /* Create a new MTU probe if we are ready. | 1153 | /* Create a new MTU probe if we are ready. |
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index ef5eaad44851..6e48f52e197c 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
| @@ -175,9 +175,16 @@ config IPV6_TUNNEL | |||
| 175 | 175 | ||
| 176 | If unsure, say N. | 176 | If unsure, say N. |
| 177 | 177 | ||
| 178 | config IPV6_MULTIPLE_TABLES | ||
| 179 | bool "IPv6: Multiple Routing Tables" | ||
| 180 | depends on IPV6 && EXPERIMENTAL | ||
| 181 | select FIB_RULES | ||
| 182 | ---help--- | ||
| 183 | Support multiple routing tables. | ||
| 184 | |||
| 178 | config IPV6_SUBTREES | 185 | config IPV6_SUBTREES |
| 179 | bool "IPv6: source address based routing" | 186 | bool "IPv6: source address based routing" |
| 180 | depends on IPV6 && EXPERIMENTAL | 187 | depends on IPV6_MULTIPLE_TABLES |
| 181 | ---help--- | 188 | ---help--- |
| 182 | Enable routing by source address or prefix. | 189 | Enable routing by source address or prefix. |
| 183 | 190 | ||
| @@ -189,13 +196,6 @@ config IPV6_SUBTREES | |||
| 189 | 196 | ||
| 190 | If unsure, say N. | 197 | If unsure, say N. |
| 191 | 198 | ||
| 192 | config IPV6_MULTIPLE_TABLES | ||
| 193 | bool "IPv6: Multiple Routing Tables" | ||
| 194 | depends on IPV6 && EXPERIMENTAL | ||
| 195 | select FIB_RULES | ||
| 196 | ---help--- | ||
| 197 | Support multiple routing tables. | ||
| 198 | |||
| 199 | config IPV6_ROUTE_FWMARK | 199 | config IPV6_ROUTE_FWMARK |
| 200 | bool "IPv6: use netfilter MARK value as routing key" | 200 | bool "IPv6: use netfilter MARK value as routing key" |
| 201 | depends on IPV6_MULTIPLE_TABLES && NETFILTER | 201 | depends on IPV6_MULTIPLE_TABLES && NETFILTER |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index a1b0f075462e..c953466b7afd 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -141,6 +141,10 @@ struct rt6_info ip6_null_entry = { | |||
| 141 | 141 | ||
| 142 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 142 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
| 143 | 143 | ||
| 144 | static int ip6_pkt_prohibit(struct sk_buff *skb); | ||
| 145 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); | ||
| 146 | static int ip6_pkt_blk_hole(struct sk_buff *skb); | ||
| 147 | |||
| 144 | struct rt6_info ip6_prohibit_entry = { | 148 | struct rt6_info ip6_prohibit_entry = { |
| 145 | .u = { | 149 | .u = { |
| 146 | .dst = { | 150 | .dst = { |
| @@ -150,8 +154,8 @@ struct rt6_info ip6_prohibit_entry = { | |||
| 150 | .obsolete = -1, | 154 | .obsolete = -1, |
| 151 | .error = -EACCES, | 155 | .error = -EACCES, |
| 152 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 156 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
| 153 | .input = ip6_pkt_discard, | 157 | .input = ip6_pkt_prohibit, |
| 154 | .output = ip6_pkt_discard_out, | 158 | .output = ip6_pkt_prohibit_out, |
| 155 | .ops = &ip6_dst_ops, | 159 | .ops = &ip6_dst_ops, |
| 156 | .path = (struct dst_entry*)&ip6_prohibit_entry, | 160 | .path = (struct dst_entry*)&ip6_prohibit_entry, |
| 157 | } | 161 | } |
| @@ -170,8 +174,8 @@ struct rt6_info ip6_blk_hole_entry = { | |||
| 170 | .obsolete = -1, | 174 | .obsolete = -1, |
| 171 | .error = -EINVAL, | 175 | .error = -EINVAL, |
| 172 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 176 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
| 173 | .input = ip6_pkt_discard, | 177 | .input = ip6_pkt_blk_hole, |
| 174 | .output = ip6_pkt_discard_out, | 178 | .output = ip6_pkt_blk_hole, |
| 175 | .ops = &ip6_dst_ops, | 179 | .ops = &ip6_dst_ops, |
| 176 | .path = (struct dst_entry*)&ip6_blk_hole_entry, | 180 | .path = (struct dst_entry*)&ip6_blk_hole_entry, |
| 177 | } | 181 | } |
| @@ -484,7 +488,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | |||
| 484 | do { \ | 488 | do { \ |
| 485 | if (rt == &ip6_null_entry) { \ | 489 | if (rt == &ip6_null_entry) { \ |
| 486 | struct fib6_node *pn; \ | 490 | struct fib6_node *pn; \ |
| 487 | while (fn) { \ | 491 | while (1) { \ |
| 488 | if (fn->fn_flags & RTN_TL_ROOT) \ | 492 | if (fn->fn_flags & RTN_TL_ROOT) \ |
| 489 | goto out; \ | 493 | goto out; \ |
| 490 | pn = fn->parent; \ | 494 | pn = fn->parent; \ |
| @@ -618,8 +622,6 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d | |||
| 618 | ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); | 622 | ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); |
| 619 | rt->rt6i_dst.plen = 128; | 623 | rt->rt6i_dst.plen = 128; |
| 620 | rt->rt6i_flags |= RTF_CACHE; | 624 | rt->rt6i_flags |= RTF_CACHE; |
| 621 | if (rt->rt6i_flags & RTF_REJECT) | ||
| 622 | rt->u.dst.error = ort->u.dst.error; | ||
| 623 | rt->u.dst.flags |= DST_HOST; | 625 | rt->u.dst.flags |= DST_HOST; |
| 624 | rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop); | 626 | rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop); |
| 625 | } | 627 | } |
| @@ -1540,6 +1542,7 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | |||
| 1540 | rt->u.dst.output = ort->u.dst.output; | 1542 | rt->u.dst.output = ort->u.dst.output; |
| 1541 | 1543 | ||
| 1542 | memcpy(rt->u.dst.metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32)); | 1544 | memcpy(rt->u.dst.metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32)); |
| 1545 | rt->u.dst.error = ort->u.dst.error; | ||
| 1543 | rt->u.dst.dev = ort->u.dst.dev; | 1546 | rt->u.dst.dev = ort->u.dst.dev; |
| 1544 | if (rt->u.dst.dev) | 1547 | if (rt->u.dst.dev) |
| 1545 | dev_hold(rt->u.dst.dev); | 1548 | dev_hold(rt->u.dst.dev); |
| @@ -1743,24 +1746,50 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg) | |||
| 1743 | * Drop the packet on the floor | 1746 | * Drop the packet on the floor |
| 1744 | */ | 1747 | */ |
| 1745 | 1748 | ||
| 1746 | static int ip6_pkt_discard(struct sk_buff *skb) | 1749 | static inline int ip6_pkt_drop(struct sk_buff *skb, int code) |
| 1747 | { | 1750 | { |
| 1748 | int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); | 1751 | int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); |
| 1749 | if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) | 1752 | if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) |
| 1750 | IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS); | 1753 | IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS); |
| 1751 | 1754 | ||
| 1752 | IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); | 1755 | IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); |
| 1753 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev); | 1756 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev); |
| 1754 | kfree_skb(skb); | 1757 | kfree_skb(skb); |
| 1755 | return 0; | 1758 | return 0; |
| 1756 | } | 1759 | } |
| 1757 | 1760 | ||
| 1761 | static int ip6_pkt_discard(struct sk_buff *skb) | ||
| 1762 | { | ||
| 1763 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE); | ||
| 1764 | } | ||
| 1765 | |||
| 1758 | static int ip6_pkt_discard_out(struct sk_buff *skb) | 1766 | static int ip6_pkt_discard_out(struct sk_buff *skb) |
| 1759 | { | 1767 | { |
| 1760 | skb->dev = skb->dst->dev; | 1768 | skb->dev = skb->dst->dev; |
| 1761 | return ip6_pkt_discard(skb); | 1769 | return ip6_pkt_discard(skb); |
| 1762 | } | 1770 | } |
| 1763 | 1771 | ||
| 1772 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
| 1773 | |||
| 1774 | static int ip6_pkt_prohibit(struct sk_buff *skb) | ||
| 1775 | { | ||
| 1776 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED); | ||
| 1777 | } | ||
| 1778 | |||
| 1779 | static int ip6_pkt_prohibit_out(struct sk_buff *skb) | ||
| 1780 | { | ||
| 1781 | skb->dev = skb->dst->dev; | ||
| 1782 | return ip6_pkt_prohibit(skb); | ||
| 1783 | } | ||
| 1784 | |||
| 1785 | static int ip6_pkt_blk_hole(struct sk_buff *skb) | ||
| 1786 | { | ||
| 1787 | kfree_skb(skb); | ||
| 1788 | return 0; | ||
| 1789 | } | ||
| 1790 | |||
| 1791 | #endif | ||
| 1792 | |||
| 1764 | /* | 1793 | /* |
| 1765 | * Allocate a dst for local (unicast / anycast) address. | 1794 | * Allocate a dst for local (unicast / anycast) address. |
| 1766 | */ | 1795 | */ |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 73cee2ec07e8..d400f8fae129 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
| @@ -25,12 +25,14 @@ | |||
| 25 | static struct dst_ops xfrm6_dst_ops; | 25 | static struct dst_ops xfrm6_dst_ops; |
| 26 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo; | 26 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo; |
| 27 | 27 | ||
| 28 | static int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl) | 28 | static int xfrm6_dst_lookup(struct xfrm_dst **xdst, struct flowi *fl) |
| 29 | { | 29 | { |
| 30 | int err = 0; | 30 | struct dst_entry *dst = ip6_route_output(NULL, fl); |
| 31 | *dst = (struct xfrm_dst*)ip6_route_output(NULL, fl); | 31 | int err = dst->error; |
| 32 | if (!*dst) | 32 | if (!err) |
| 33 | err = -ENETUNREACH; | 33 | *xdst = (struct xfrm_dst *) dst; |
| 34 | else | ||
| 35 | dst_release(dst); | ||
| 34 | return err; | 36 | return err; |
| 35 | } | 37 | } |
| 36 | 38 | ||
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 249e5033c1a8..78071c6e6cf1 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
| @@ -215,17 +215,17 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, | |||
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | dst = ip6_route_output(NULL, &fl); | 217 | dst = ip6_route_output(NULL, &fl); |
| 218 | if (dst) { | 218 | if (!dst->error) { |
| 219 | struct rt6_info *rt; | 219 | struct rt6_info *rt; |
| 220 | rt = (struct rt6_info *)dst; | 220 | rt = (struct rt6_info *)dst; |
| 221 | SCTP_DEBUG_PRINTK( | 221 | SCTP_DEBUG_PRINTK( |
| 222 | "rt6_dst:" NIP6_FMT " rt6_src:" NIP6_FMT "\n", | 222 | "rt6_dst:" NIP6_FMT " rt6_src:" NIP6_FMT "\n", |
| 223 | NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr)); | 223 | NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr)); |
| 224 | } else { | 224 | return dst; |
| 225 | SCTP_DEBUG_PRINTK("NO ROUTE\n"); | ||
| 226 | } | 225 | } |
| 227 | 226 | SCTP_DEBUG_PRINTK("NO ROUTE\n"); | |
| 228 | return dst; | 227 | dst_release(dst); |
| 228 | return NULL; | ||
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | /* Returns the number of consecutive initial bits that match in the 2 ipv6 | 231 | /* Returns the number of consecutive initial bits that match in the 2 ipv6 |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 9deec4391187..9f34dec6ff8e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -821,7 +821,7 @@ out: | |||
| 821 | * addrs is a pointer to an array of one or more socket addresses. Each | 821 | * addrs is a pointer to an array of one or more socket addresses. Each |
| 822 | * address is contained in its appropriate structure (i.e. struct | 822 | * address is contained in its appropriate structure (i.e. struct |
| 823 | * sockaddr_in or struct sockaddr_in6) the family of the address type | 823 | * sockaddr_in or struct sockaddr_in6) the family of the address type |
| 824 | * must be used to distengish the address length (note that this | 824 | * must be used to distinguish the address length (note that this |
| 825 | * representation is termed a "packed array" of addresses). The caller | 825 | * representation is termed a "packed array" of addresses). The caller |
| 826 | * specifies the number of addresses in the array with addrcnt. | 826 | * specifies the number of addresses in the array with addrcnt. |
| 827 | * | 827 | * |
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 75a5968c2139..39744a33bd36 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * net/tipc/bearer.c: TIPC bearer code | 2 | * net/tipc/bearer.c: TIPC bearer code |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 1996-2006, Ericsson AB | 4 | * Copyright (c) 1996-2006, Ericsson AB |
| 5 | * Copyright (c) 2004-2005, Wind River Systems | 5 | * Copyright (c) 2004-2006, Wind River Systems |
| 6 | * All rights reserved. | 6 | * All rights reserved. |
| 7 | * | 7 | * |
| 8 | * Redistribution and use in source and binary forms, with or without | 8 | * 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) | |||
| 191 | if ((i < media_count) && (m_ptr->addr2str != NULL)) { | 191 | if ((i < media_count) && (m_ptr->addr2str != NULL)) { |
| 192 | char addr_str[MAX_ADDR_STR]; | 192 | char addr_str[MAX_ADDR_STR]; |
| 193 | 193 | ||
| 194 | tipc_printf(pb, "%s(%s) ", m_ptr->name, | 194 | tipc_printf(pb, "%s(%s)", m_ptr->name, |
| 195 | m_ptr->addr2str(a, addr_str, sizeof(addr_str))); | 195 | m_ptr->addr2str(a, addr_str, sizeof(addr_str))); |
| 196 | } else { | 196 | } else { |
| 197 | unchar *addr = (unchar *)&a->dev_addr; | 197 | unchar *addr = (unchar *)&a->dev_addr; |
| 198 | 198 | ||
| 199 | tipc_printf(pb, "UNKNOWN(%u):", media_type); | 199 | tipc_printf(pb, "UNKNOWN(%u)", media_type); |
| 200 | for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++) { | 200 | for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++) { |
| 201 | tipc_printf(pb, "%02x ", addr[i]); | 201 | tipc_printf(pb, "-%02x", addr[i]); |
| 202 | } | 202 | } |
| 203 | } | 203 | } |
| 204 | } | 204 | } |
diff --git a/net/tipc/config.c b/net/tipc/config.c index 285e1bc2d880..ed1351ed05e1 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * net/tipc/config.c: TIPC configuration management code | 2 | * net/tipc/config.c: TIPC configuration management code |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2002-2006, Ericsson AB | 4 | * Copyright (c) 2002-2006, Ericsson AB |
| 5 | * Copyright (c) 2004-2005, Wind River Systems | 5 | * Copyright (c) 2004-2006, Wind River Systems |
| 6 | * All rights reserved. | 6 | * All rights reserved. |
| 7 | * | 7 | * |
| 8 | * Redistribution and use in source and binary forms, with or without | 8 | * 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 | |||
| 613 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id); | 613 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id); |
| 614 | break; | 614 | break; |
| 615 | default: | 615 | default: |
| 616 | rep_tlv_buf = NULL; | 616 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
| 617 | " (unknown command)"); | ||
| 617 | break; | 618 | break; |
| 618 | } | 619 | } |
| 619 | 620 | ||
diff --git a/net/tipc/core.c b/net/tipc/core.c index 0539a8362858..6f5b7ee31180 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
| @@ -57,7 +57,7 @@ void tipc_socket_stop(void); | |||
| 57 | int tipc_netlink_start(void); | 57 | int tipc_netlink_start(void); |
| 58 | void tipc_netlink_stop(void); | 58 | void tipc_netlink_stop(void); |
| 59 | 59 | ||
| 60 | #define TIPC_MOD_VER "1.6.1" | 60 | #define TIPC_MOD_VER "1.6.2" |
| 61 | 61 | ||
| 62 | #ifndef CONFIG_TIPC_ZONES | 62 | #ifndef CONFIG_TIPC_ZONES |
| 63 | #define CONFIG_TIPC_ZONES 3 | 63 | #define CONFIG_TIPC_ZONES 3 |
| @@ -90,7 +90,7 @@ int tipc_random; | |||
| 90 | atomic_t tipc_user_count = ATOMIC_INIT(0); | 90 | atomic_t tipc_user_count = ATOMIC_INIT(0); |
| 91 | 91 | ||
| 92 | const char tipc_alphabet[] = | 92 | const char tipc_alphabet[] = |
| 93 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; | 93 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_."; |
| 94 | 94 | ||
| 95 | /* configurable TIPC parameters */ | 95 | /* configurable TIPC parameters */ |
| 96 | 96 | ||
diff --git a/net/tipc/core.h b/net/tipc/core.h index 762aac2572be..4638947c2326 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h | |||
| @@ -65,7 +65,7 @@ | |||
| 65 | #define assert(i) BUG_ON(!(i)) | 65 | #define assert(i) BUG_ON(!(i)) |
| 66 | 66 | ||
| 67 | struct tipc_msg; | 67 | struct tipc_msg; |
| 68 | extern struct print_buf *TIPC_CONS, *TIPC_LOG; | 68 | extern struct print_buf *TIPC_NULL, *TIPC_CONS, *TIPC_LOG; |
| 69 | extern struct print_buf *TIPC_TEE(struct print_buf *, struct print_buf *); | 69 | extern struct print_buf *TIPC_TEE(struct print_buf *, struct print_buf *); |
| 70 | void tipc_msg_print(struct print_buf*,struct tipc_msg *,const char*); | 70 | void tipc_msg_print(struct print_buf*,struct tipc_msg *,const char*); |
| 71 | void tipc_printf(struct print_buf *, const char *fmt, ...); | 71 | void tipc_printf(struct print_buf *, const char *fmt, ...); |
| @@ -83,9 +83,9 @@ void tipc_dump(struct print_buf*,const char *fmt, ...); | |||
| 83 | #define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_WARNING "TIPC: " fmt, ## arg) | 83 | #define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_WARNING "TIPC: " fmt, ## arg) |
| 84 | #define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_NOTICE "TIPC: " fmt, ## arg) | 84 | #define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_NOTICE "TIPC: " fmt, ## arg) |
| 85 | 85 | ||
| 86 | #define dbg(fmt, arg...) do {if (DBG_OUTPUT) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0) | 86 | #define dbg(fmt, arg...) do {if (DBG_OUTPUT != TIPC_NULL) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0) |
| 87 | #define msg_dbg(msg, txt) do {if (DBG_OUTPUT) tipc_msg_print(DBG_OUTPUT, msg, txt);} while(0) | 87 | #define msg_dbg(msg, txt) do {if (DBG_OUTPUT != TIPC_NULL) tipc_msg_print(DBG_OUTPUT, msg, txt);} while(0) |
| 88 | #define dump(fmt, arg...) do {if (DBG_OUTPUT) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0) | 88 | #define dump(fmt, arg...) do {if (DBG_OUTPUT != TIPC_NULL) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0) |
| 89 | 89 | ||
| 90 | 90 | ||
| 91 | /* | 91 | /* |
| @@ -94,11 +94,11 @@ void tipc_dump(struct print_buf*,const char *fmt, ...); | |||
| 94 | * here, or on a per .c file basis, by redefining these symbols. The following | 94 | * here, or on a per .c file basis, by redefining these symbols. The following |
| 95 | * print buffer options are available: | 95 | * print buffer options are available: |
| 96 | * | 96 | * |
| 97 | * NULL : Output to null print buffer (i.e. print nowhere) | 97 | * TIPC_NULL : null buffer (i.e. print nowhere) |
| 98 | * TIPC_CONS : Output to system console | 98 | * TIPC_CONS : system console |
| 99 | * TIPC_LOG : Output to TIPC log buffer | 99 | * TIPC_LOG : TIPC log buffer |
| 100 | * &buf : Output to user-defined buffer (struct print_buf *) | 100 | * &buf : user-defined buffer (struct print_buf *) |
| 101 | * TIPC_TEE(&buf_a,&buf_b) : Output to two print buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG) ) | 101 | * TIPC_TEE(&buf_a,&buf_b) : list of buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG)) |
| 102 | */ | 102 | */ |
| 103 | 103 | ||
| 104 | #ifndef TIPC_OUTPUT | 104 | #ifndef TIPC_OUTPUT |
| @@ -106,7 +106,7 @@ void tipc_dump(struct print_buf*,const char *fmt, ...); | |||
| 106 | #endif | 106 | #endif |
| 107 | 107 | ||
| 108 | #ifndef DBG_OUTPUT | 108 | #ifndef DBG_OUTPUT |
| 109 | #define DBG_OUTPUT NULL | 109 | #define DBG_OUTPUT TIPC_NULL |
| 110 | #endif | 110 | #endif |
| 111 | 111 | ||
| 112 | #else | 112 | #else |
| @@ -136,7 +136,7 @@ void tipc_dump(struct print_buf*,const char *fmt, ...); | |||
| 136 | #define TIPC_OUTPUT TIPC_CONS | 136 | #define TIPC_OUTPUT TIPC_CONS |
| 137 | 137 | ||
| 138 | #undef DBG_OUTPUT | 138 | #undef DBG_OUTPUT |
| 139 | #define DBG_OUTPUT NULL | 139 | #define DBG_OUTPUT TIPC_NULL |
| 140 | 140 | ||
| 141 | #endif | 141 | #endif |
| 142 | 142 | ||
| @@ -275,11 +275,15 @@ static inline void k_term_timer(struct timer_list *timer) | |||
| 275 | /* | 275 | /* |
| 276 | * TIPC message buffer code | 276 | * TIPC message buffer code |
| 277 | * | 277 | * |
| 278 | * TIPC message buffer headroom leaves room for 14 byte Ethernet header, | 278 | * TIPC message buffer headroom reserves space for a link-level header |
| 279 | * (in case the message is sent off-node), | ||
| 279 | * while ensuring TIPC header is word aligned for quicker access | 280 | * while ensuring TIPC header is word aligned for quicker access |
| 281 | * | ||
| 282 | * The largest header currently supported is 18 bytes, which is used when | ||
| 283 | * the standard 14 byte Ethernet header has 4 added bytes for VLAN info | ||
| 280 | */ | 284 | */ |
| 281 | 285 | ||
| 282 | #define BUF_HEADROOM 16u | 286 | #define BUF_HEADROOM 20u |
| 283 | 287 | ||
| 284 | struct tipc_skb_cb { | 288 | struct tipc_skb_cb { |
| 285 | void *handle; | 289 | void *handle; |
diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c index 55130655e1ed..d8af4c28695d 100644 --- a/net/tipc/dbg.c +++ b/net/tipc/dbg.c | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * net/tipc/dbg.c: TIPC print buffer routines for debuggign | 2 | * net/tipc/dbg.c: TIPC print buffer routines for debugging |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 1996-2006, Ericsson AB | 4 | * Copyright (c) 1996-2006, Ericsson AB |
| 5 | * Copyright (c) 2005, Wind River Systems | 5 | * Copyright (c) 2005-2006, Wind River Systems |
| 6 | * All rights reserved. | 6 | * All rights reserved. |
| 7 | * | 7 | * |
| 8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
| @@ -38,11 +38,12 @@ | |||
| 38 | #include "config.h" | 38 | #include "config.h" |
| 39 | #include "dbg.h" | 39 | #include "dbg.h" |
| 40 | 40 | ||
| 41 | #define MAX_STRING 512 | 41 | static char print_string[TIPC_PB_MAX_STR]; |
| 42 | |||
| 43 | static char print_string[MAX_STRING]; | ||
| 44 | static DEFINE_SPINLOCK(print_lock); | 42 | static DEFINE_SPINLOCK(print_lock); |
| 45 | 43 | ||
| 44 | static struct print_buf null_buf = { NULL, 0, NULL, NULL }; | ||
| 45 | struct print_buf *TIPC_NULL = &null_buf; | ||
| 46 | |||
| 46 | static struct print_buf cons_buf = { NULL, 0, NULL, NULL }; | 47 | static struct print_buf cons_buf = { NULL, 0, NULL, NULL }; |
| 47 | struct print_buf *TIPC_CONS = &cons_buf; | 48 | struct print_buf *TIPC_CONS = &cons_buf; |
| 48 | 49 | ||
| @@ -62,68 +63,83 @@ struct print_buf *TIPC_LOG = &log_buf; | |||
| 62 | /* | 63 | /* |
| 63 | * Locking policy when using print buffers. | 64 | * Locking policy when using print buffers. |
| 64 | * | 65 | * |
| 65 | * 1) Routines of the form printbuf_XXX() rely on the caller to prevent | 66 | * The following routines use 'print_lock' for protection: |
| 66 | * simultaneous use of the print buffer(s) being manipulated. | 67 | * 1) tipc_printf() - to protect its print buffer(s) and 'print_string' |
| 67 | * 2) tipc_printf() uses 'print_lock' to prevent simultaneous use of | 68 | * 2) TIPC_TEE() - to protect its print buffer(s) |
| 68 | * 'print_string' and to protect its print buffer(s). | 69 | * 3) tipc_dump() - to protect its print buffer(s) and 'print_string' |
| 69 | * 3) TIPC_TEE() uses 'print_lock' to protect its print buffer(s). | 70 | * 4) tipc_log_XXX() - to protect TIPC_LOG |
| 70 | * 4) Routines of the form log_XXX() uses 'print_lock' to protect TIPC_LOG. | 71 | * |
| 72 | * All routines of the form tipc_printbuf_XXX() rely on the caller to prevent | ||
| 73 | * simultaneous use of the print buffer(s) being manipulated. | ||
| 71 | */ | 74 | */ |
| 72 | 75 | ||
| 73 | /** | 76 | /** |
| 74 | * tipc_printbuf_init - initialize print buffer to empty | 77 | * tipc_printbuf_init - initialize print buffer to empty |
| 78 | * @pb: pointer to print buffer structure | ||
| 79 | * @raw: pointer to character array used by print buffer | ||
| 80 | * @size: size of character array | ||
| 81 | * | ||
| 82 | * Makes the print buffer a null device that discards anything written to it | ||
| 83 | * if the character array is too small (or absent). | ||
| 75 | */ | 84 | */ |
| 76 | 85 | ||
| 77 | void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 sz) | 86 | void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size) |
| 78 | { | 87 | { |
| 79 | if (!pb || !raw || (sz < (MAX_STRING + 1))) | 88 | pb->buf = raw; |
| 80 | return; | 89 | pb->crs = raw; |
| 81 | 90 | pb->size = size; | |
| 82 | pb->crs = pb->buf = raw; | ||
| 83 | pb->size = sz; | ||
| 84 | pb->next = NULL; | 91 | pb->next = NULL; |
| 85 | pb->buf[0] = 0; | 92 | |
| 86 | pb->buf[sz-1] = ~0; | 93 | if (size < TIPC_PB_MIN_SIZE) { |
| 94 | pb->buf = NULL; | ||
| 95 | } else if (raw) { | ||
| 96 | pb->buf[0] = 0; | ||
| 97 | pb->buf[size-1] = ~0; | ||
| 98 | } | ||
| 87 | } | 99 | } |
| 88 | 100 | ||
| 89 | /** | 101 | /** |
| 90 | * tipc_printbuf_reset - reinitialize print buffer to empty state | 102 | * tipc_printbuf_reset - reinitialize print buffer to empty state |
| 103 | * @pb: pointer to print buffer structure | ||
| 91 | */ | 104 | */ |
| 92 | 105 | ||
| 93 | void tipc_printbuf_reset(struct print_buf *pb) | 106 | void tipc_printbuf_reset(struct print_buf *pb) |
| 94 | { | 107 | { |
| 95 | if (pb && pb->buf) | 108 | tipc_printbuf_init(pb, pb->buf, pb->size); |
| 96 | tipc_printbuf_init(pb, pb->buf, pb->size); | ||
| 97 | } | 109 | } |
| 98 | 110 | ||
| 99 | /** | 111 | /** |
| 100 | * tipc_printbuf_empty - test if print buffer is in empty state | 112 | * tipc_printbuf_empty - test if print buffer is in empty state |
| 113 | * @pb: pointer to print buffer structure | ||
| 114 | * | ||
| 115 | * Returns non-zero if print buffer is empty. | ||
| 101 | */ | 116 | */ |
| 102 | 117 | ||
| 103 | int tipc_printbuf_empty(struct print_buf *pb) | 118 | int tipc_printbuf_empty(struct print_buf *pb) |
| 104 | { | 119 | { |
| 105 | return (!pb || !pb->buf || (pb->crs == pb->buf)); | 120 | return (!pb->buf || (pb->crs == pb->buf)); |
| 106 | } | 121 | } |
| 107 | 122 | ||
| 108 | /** | 123 | /** |
| 109 | * tipc_printbuf_validate - check for print buffer overflow | 124 | * tipc_printbuf_validate - check for print buffer overflow |
| 125 | * @pb: pointer to print buffer structure | ||
| 110 | * | 126 | * |
| 111 | * Verifies that a print buffer has captured all data written to it. | 127 | * Verifies that a print buffer has captured all data written to it. |
| 112 | * If data has been lost, linearize buffer and prepend an error message | 128 | * If data has been lost, linearize buffer and prepend an error message |
| 113 | * | 129 | * |
| 114 | * Returns length of print buffer data string (including trailing NULL) | 130 | * Returns length of print buffer data string (including trailing NUL) |
| 115 | */ | 131 | */ |
| 116 | 132 | ||
| 117 | int tipc_printbuf_validate(struct print_buf *pb) | 133 | int tipc_printbuf_validate(struct print_buf *pb) |
| 118 | { | 134 | { |
| 119 | char *err = " *** PRINT BUFFER WRAPPED AROUND ***\n"; | 135 | char *err = "\n\n*** PRINT BUFFER OVERFLOW ***\n\n"; |
| 120 | char *cp_buf; | 136 | char *cp_buf; |
| 121 | struct print_buf cb; | 137 | struct print_buf cb; |
| 122 | 138 | ||
| 123 | if (!pb || !pb->buf) | 139 | if (!pb->buf) |
| 124 | return 0; | 140 | return 0; |
| 125 | 141 | ||
| 126 | if (pb->buf[pb->size - 1] == '\0') { | 142 | if (pb->buf[pb->size - 1] == 0) { |
| 127 | cp_buf = kmalloc(pb->size, GFP_ATOMIC); | 143 | cp_buf = kmalloc(pb->size, GFP_ATOMIC); |
| 128 | if (cp_buf != NULL){ | 144 | if (cp_buf != NULL){ |
| 129 | tipc_printbuf_init(&cb, cp_buf, pb->size); | 145 | tipc_printbuf_init(&cb, cp_buf, pb->size); |
| @@ -141,6 +157,8 @@ int tipc_printbuf_validate(struct print_buf *pb) | |||
| 141 | 157 | ||
| 142 | /** | 158 | /** |
| 143 | * tipc_printbuf_move - move print buffer contents to another print buffer | 159 | * tipc_printbuf_move - move print buffer contents to another print buffer |
| 160 | * @pb_to: pointer to destination print buffer structure | ||
| 161 | * @pb_from: pointer to source print buffer structure | ||
| 144 | * | 162 | * |
| 145 | * Current contents of destination print buffer (if any) are discarded. | 163 | * Current contents of destination print buffer (if any) are discarded. |
| 146 | * Source print buffer becomes empty if a successful move occurs. | 164 | * 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) | |||
| 152 | 170 | ||
| 153 | /* Handle the cases where contents can't be moved */ | 171 | /* Handle the cases where contents can't be moved */ |
| 154 | 172 | ||
| 155 | if (!pb_to || !pb_to->buf) | 173 | if (!pb_to->buf) |
| 156 | return; | 174 | return; |
| 157 | 175 | ||
| 158 | if (!pb_from || !pb_from->buf) { | 176 | if (!pb_from->buf) { |
| 159 | tipc_printbuf_reset(pb_to); | 177 | tipc_printbuf_reset(pb_to); |
| 160 | return; | 178 | return; |
| 161 | } | 179 | } |
| 162 | 180 | ||
| 163 | if (pb_to->size < pb_from->size) { | 181 | if (pb_to->size < pb_from->size) { |
| 164 | tipc_printbuf_reset(pb_to); | 182 | tipc_printbuf_reset(pb_to); |
| 165 | tipc_printf(pb_to, "*** PRINT BUFFER OVERFLOW ***"); | 183 | tipc_printf(pb_to, "*** PRINT BUFFER MOVE ERROR ***"); |
| 166 | return; | 184 | return; |
| 167 | } | 185 | } |
| 168 | 186 | ||
| 169 | /* Copy data from char after cursor to end (if used) */ | 187 | /* Copy data from char after cursor to end (if used) */ |
| 188 | |||
| 170 | len = pb_from->buf + pb_from->size - pb_from->crs - 2; | 189 | len = pb_from->buf + pb_from->size - pb_from->crs - 2; |
| 171 | if ((pb_from->buf[pb_from->size-1] == 0) && (len > 0)) { | 190 | if ((pb_from->buf[pb_from->size-1] == 0) && (len > 0)) { |
| 172 | strcpy(pb_to->buf, pb_from->crs + 1); | 191 | 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) | |||
| 175 | pb_to->crs = pb_to->buf; | 194 | pb_to->crs = pb_to->buf; |
| 176 | 195 | ||
| 177 | /* Copy data from start to cursor (always) */ | 196 | /* Copy data from start to cursor (always) */ |
| 197 | |||
| 178 | len = pb_from->crs - pb_from->buf; | 198 | len = pb_from->crs - pb_from->buf; |
| 179 | strcpy(pb_to->crs, pb_from->buf); | 199 | strcpy(pb_to->crs, pb_from->buf); |
| 180 | pb_to->crs += len; | 200 | pb_to->crs += len; |
| @@ -184,6 +204,8 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from) | |||
| 184 | 204 | ||
| 185 | /** | 205 | /** |
| 186 | * tipc_printf - append formatted output to print buffer chain | 206 | * tipc_printf - append formatted output to print buffer chain |
| 207 | * @pb: pointer to chain of print buffers (may be NULL) | ||
| 208 | * @fmt: formatted info to be printed | ||
| 187 | */ | 209 | */ |
| 188 | 210 | ||
| 189 | void tipc_printf(struct print_buf *pb, const char *fmt, ...) | 211 | void tipc_printf(struct print_buf *pb, const char *fmt, ...) |
| @@ -195,8 +217,8 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...) | |||
| 195 | 217 | ||
| 196 | spin_lock_bh(&print_lock); | 218 | spin_lock_bh(&print_lock); |
| 197 | FORMAT(print_string, chars_to_add, fmt); | 219 | FORMAT(print_string, chars_to_add, fmt); |
| 198 | if (chars_to_add >= MAX_STRING) | 220 | if (chars_to_add >= TIPC_PB_MAX_STR) |
| 199 | strcpy(print_string, "*** STRING TOO LONG ***"); | 221 | strcpy(print_string, "*** PRINT BUFFER STRING TOO LONG ***"); |
| 200 | 222 | ||
| 201 | while (pb) { | 223 | while (pb) { |
| 202 | if (pb == TIPC_CONS) | 224 | if (pb == TIPC_CONS) |
| @@ -206,6 +228,10 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...) | |||
| 206 | if (chars_to_add <= chars_left) { | 228 | if (chars_to_add <= chars_left) { |
| 207 | strcpy(pb->crs, print_string); | 229 | strcpy(pb->crs, print_string); |
| 208 | pb->crs += chars_to_add; | 230 | pb->crs += chars_to_add; |
| 231 | } else if (chars_to_add >= (pb->size - 1)) { | ||
| 232 | strcpy(pb->buf, print_string + chars_to_add + 1 | ||
| 233 | - pb->size); | ||
| 234 | pb->crs = pb->buf + pb->size - 1; | ||
| 209 | } else { | 235 | } else { |
| 210 | strcpy(pb->buf, print_string + chars_left); | 236 | strcpy(pb->buf, print_string + chars_left); |
| 211 | save_char = print_string[chars_left]; | 237 | save_char = print_string[chars_left]; |
| @@ -224,6 +250,10 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...) | |||
| 224 | 250 | ||
| 225 | /** | 251 | /** |
| 226 | * TIPC_TEE - perform next output operation on both print buffers | 252 | * TIPC_TEE - perform next output operation on both print buffers |
| 253 | * @b0: pointer to chain of print buffers (may be NULL) | ||
| 254 | * @b1: pointer to print buffer to add to chain | ||
| 255 | * | ||
| 256 | * Returns pointer to print buffer chain. | ||
| 227 | */ | 257 | */ |
| 228 | 258 | ||
| 229 | struct print_buf *TIPC_TEE(struct print_buf *b0, struct print_buf *b1) | 259 | 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) | |||
| 232 | 262 | ||
| 233 | if (!b0 || (b0 == b1)) | 263 | if (!b0 || (b0 == b1)) |
| 234 | return b1; | 264 | return b1; |
| 235 | if (!b1) | ||
| 236 | return b0; | ||
| 237 | 265 | ||
| 238 | spin_lock_bh(&print_lock); | 266 | spin_lock_bh(&print_lock); |
| 239 | while (pb->next) { | 267 | while (pb->next) { |
| @@ -256,7 +284,7 @@ static void print_to_console(char *crs, int len) | |||
| 256 | int rest = len; | 284 | int rest = len; |
| 257 | 285 | ||
| 258 | while (rest > 0) { | 286 | while (rest > 0) { |
| 259 | int sz = rest < MAX_STRING ? rest : MAX_STRING; | 287 | int sz = rest < TIPC_PB_MAX_STR ? rest : TIPC_PB_MAX_STR; |
| 260 | char c = crs[sz]; | 288 | char c = crs[sz]; |
| 261 | 289 | ||
| 262 | crs[sz] = 0; | 290 | crs[sz] = 0; |
| @@ -275,36 +303,48 @@ static void printbuf_dump(struct print_buf *pb) | |||
| 275 | { | 303 | { |
| 276 | int len; | 304 | int len; |
| 277 | 305 | ||
| 306 | if (!pb->buf) { | ||
| 307 | printk("*** PRINT BUFFER NOT ALLOCATED ***"); | ||
| 308 | return; | ||
| 309 | } | ||
| 310 | |||
| 278 | /* Dump print buffer from char after cursor to end (if used) */ | 311 | /* Dump print buffer from char after cursor to end (if used) */ |
| 312 | |||
| 279 | len = pb->buf + pb->size - pb->crs - 2; | 313 | len = pb->buf + pb->size - pb->crs - 2; |
| 280 | if ((pb->buf[pb->size - 1] == 0) && (len > 0)) | 314 | if ((pb->buf[pb->size - 1] == 0) && (len > 0)) |
| 281 | print_to_console(pb->crs + 1, len); | 315 | print_to_console(pb->crs + 1, len); |
| 282 | 316 | ||
| 283 | /* Dump print buffer from start to cursor (always) */ | 317 | /* Dump print buffer from start to cursor (always) */ |
| 318 | |||
| 284 | len = pb->crs - pb->buf; | 319 | len = pb->crs - pb->buf; |
| 285 | print_to_console(pb->buf, len); | 320 | print_to_console(pb->buf, len); |
| 286 | } | 321 | } |
| 287 | 322 | ||
| 288 | /** | 323 | /** |
| 289 | * tipc_dump - dump non-console print buffer(s) to console | 324 | * tipc_dump - dump non-console print buffer(s) to console |
| 325 | * @pb: pointer to chain of print buffers | ||
| 290 | */ | 326 | */ |
| 291 | 327 | ||
| 292 | void tipc_dump(struct print_buf *pb, const char *fmt, ...) | 328 | void tipc_dump(struct print_buf *pb, const char *fmt, ...) |
| 293 | { | 329 | { |
| 330 | struct print_buf *pb_next; | ||
| 294 | int len; | 331 | int len; |
| 295 | 332 | ||
| 296 | spin_lock_bh(&print_lock); | 333 | spin_lock_bh(&print_lock); |
| 297 | FORMAT(TIPC_CONS->buf, len, fmt); | 334 | FORMAT(print_string, len, fmt); |
| 298 | printk(TIPC_CONS->buf); | 335 | printk(print_string); |
| 299 | 336 | ||
| 300 | for (; pb; pb = pb->next) { | 337 | for (; pb; pb = pb->next) { |
| 301 | if (pb == TIPC_CONS) | 338 | if (pb != TIPC_CONS) { |
| 302 | continue; | 339 | printk("\n---- Start of %s log dump ----\n\n", |
| 303 | printk("\n---- Start of dump,%s log ----\n\n", | 340 | (pb == TIPC_LOG) ? "global" : "local"); |
| 304 | (pb == TIPC_LOG) ? "global" : "local"); | 341 | printbuf_dump(pb); |
| 305 | printbuf_dump(pb); | 342 | tipc_printbuf_reset(pb); |
| 306 | tipc_printbuf_reset(pb); | 343 | printk("\n---- End of dump ----\n"); |
| 307 | printk("\n-------- End of dump --------\n"); | 344 | } |
| 345 | pb_next = pb->next; | ||
| 346 | pb->next = NULL; | ||
| 347 | pb = pb_next; | ||
| 308 | } | 348 | } |
| 309 | spin_unlock_bh(&print_lock); | 349 | spin_unlock_bh(&print_lock); |
| 310 | } | 350 | } |
| @@ -324,7 +364,8 @@ void tipc_log_stop(void) | |||
| 324 | } | 364 | } |
| 325 | 365 | ||
| 326 | /** | 366 | /** |
| 327 | * tipc_log_reinit - set TIPC log print buffer to specified size | 367 | * tipc_log_reinit - (re)initialize TIPC log print buffer |
| 368 | * @log_size: print buffer size to use | ||
| 328 | */ | 369 | */ |
| 329 | 370 | ||
| 330 | void tipc_log_reinit(int log_size) | 371 | void tipc_log_reinit(int log_size) |
| @@ -332,10 +373,11 @@ void tipc_log_reinit(int log_size) | |||
| 332 | tipc_log_stop(); | 373 | tipc_log_stop(); |
| 333 | 374 | ||
| 334 | if (log_size) { | 375 | if (log_size) { |
| 335 | if (log_size <= MAX_STRING) | 376 | if (log_size < TIPC_PB_MIN_SIZE) |
| 336 | log_size = MAX_STRING + 1; | 377 | log_size = TIPC_PB_MIN_SIZE; |
| 337 | spin_lock_bh(&print_lock); | 378 | spin_lock_bh(&print_lock); |
| 338 | tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC), log_size); | 379 | tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC), |
| 380 | log_size); | ||
| 339 | spin_unlock_bh(&print_lock); | 381 | spin_unlock_bh(&print_lock); |
| 340 | } | 382 | } |
| 341 | } | 383 | } |
diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h index 227f050d2a52..467c0bc78a79 100644 --- a/net/tipc/dbg.h +++ b/net/tipc/dbg.h | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * net/tipc/dbg.h: Include file for TIPC print buffer routines | 2 | * net/tipc/dbg.h: Include file for TIPC print buffer routines |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 1997-2006, Ericsson AB | 4 | * Copyright (c) 1997-2006, Ericsson AB |
| 5 | * Copyright (c) 2005, Wind River Systems | 5 | * Copyright (c) 2005-2006, Wind River Systems |
| 6 | * All rights reserved. | 6 | * All rights reserved. |
| 7 | * | 7 | * |
| 8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
| @@ -37,6 +37,14 @@ | |||
| 37 | #ifndef _TIPC_DBG_H | 37 | #ifndef _TIPC_DBG_H |
| 38 | #define _TIPC_DBG_H | 38 | #define _TIPC_DBG_H |
| 39 | 39 | ||
| 40 | /** | ||
| 41 | * struct print_buf - TIPC print buffer structure | ||
| 42 | * @buf: pointer to character array containing print buffer contents | ||
| 43 | * @size: size of character array | ||
| 44 | * @crs: pointer to first unused space in character array (i.e. final NUL) | ||
| 45 | * @next: used to link print buffers when printing to more than one at a time | ||
| 46 | */ | ||
| 47 | |||
| 40 | struct print_buf { | 48 | struct print_buf { |
| 41 | char *buf; | 49 | char *buf; |
| 42 | u32 size; | 50 | u32 size; |
| @@ -44,7 +52,10 @@ struct print_buf { | |||
| 44 | struct print_buf *next; | 52 | struct print_buf *next; |
| 45 | }; | 53 | }; |
| 46 | 54 | ||
| 47 | void tipc_printbuf_init(struct print_buf *pb, char *buf, u32 sz); | 55 | #define TIPC_PB_MIN_SIZE 64 /* minimum size for a print buffer's array */ |
| 56 | #define TIPC_PB_MAX_STR 512 /* max printable string (with trailing NUL) */ | ||
| 57 | |||
| 58 | void tipc_printbuf_init(struct print_buf *pb, char *buf, u32 size); | ||
| 48 | void tipc_printbuf_reset(struct print_buf *pb); | 59 | void tipc_printbuf_reset(struct print_buf *pb); |
| 49 | int tipc_printbuf_empty(struct print_buf *pb); | 60 | int tipc_printbuf_empty(struct print_buf *pb); |
| 50 | int tipc_printbuf_validate(struct print_buf *pb); | 61 | int tipc_printbuf_validate(struct print_buf *pb); |
diff --git a/net/tipc/discover.c b/net/tipc/discover.c index ee94de92ae99..3b0cd12f37da 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c | |||
| @@ -132,6 +132,28 @@ static struct sk_buff *tipc_disc_init_msg(u32 type, | |||
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | /** | 134 | /** |
| 135 | * disc_dupl_alert - issue node address duplication alert | ||
| 136 | * @b_ptr: pointer to bearer detecting duplication | ||
| 137 | * @node_addr: duplicated node address | ||
| 138 | * @media_addr: media address advertised by duplicated node | ||
| 139 | */ | ||
| 140 | |||
| 141 | static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr, | ||
| 142 | struct tipc_media_addr *media_addr) | ||
| 143 | { | ||
| 144 | char node_addr_str[16]; | ||
| 145 | char media_addr_str[64]; | ||
| 146 | struct print_buf pb; | ||
| 147 | |||
| 148 | addr_string_fill(node_addr_str, node_addr); | ||
| 149 | tipc_printbuf_init(&pb, media_addr_str, sizeof(media_addr_str)); | ||
| 150 | tipc_media_addr_printf(&pb, media_addr); | ||
| 151 | tipc_printbuf_validate(&pb); | ||
| 152 | warn("Duplicate %s using %s seen on <%s>\n", | ||
| 153 | node_addr_str, media_addr_str, b_ptr->publ.name); | ||
| 154 | } | ||
| 155 | |||
| 156 | /** | ||
| 135 | * tipc_disc_recv_msg - handle incoming link setup message (request or response) | 157 | * tipc_disc_recv_msg - handle incoming link setup message (request or response) |
| 136 | * @buf: buffer containing message | 158 | * @buf: buffer containing message |
| 137 | */ | 159 | */ |
| @@ -157,8 +179,11 @@ void tipc_disc_recv_msg(struct sk_buff *buf) | |||
| 157 | return; | 179 | return; |
| 158 | if (!tipc_addr_node_valid(orig)) | 180 | if (!tipc_addr_node_valid(orig)) |
| 159 | return; | 181 | return; |
| 160 | if (orig == tipc_own_addr) | 182 | if (orig == tipc_own_addr) { |
| 183 | if (memcmp(&media_addr, &b_ptr->publ.addr, sizeof(media_addr))) | ||
| 184 | disc_dupl_alert(b_ptr, tipc_own_addr, &media_addr); | ||
| 161 | return; | 185 | return; |
| 186 | } | ||
| 162 | if (!in_scope(dest, tipc_own_addr)) | 187 | if (!in_scope(dest, tipc_own_addr)) |
| 163 | return; | 188 | return; |
| 164 | if (is_slave(tipc_own_addr) && is_slave(orig)) | 189 | if (is_slave(tipc_own_addr) && is_slave(orig)) |
| @@ -170,7 +195,8 @@ void tipc_disc_recv_msg(struct sk_buff *buf) | |||
| 170 | struct sk_buff *rbuf; | 195 | struct sk_buff *rbuf; |
| 171 | struct tipc_media_addr *addr; | 196 | struct tipc_media_addr *addr; |
| 172 | struct node *n_ptr = tipc_node_find(orig); | 197 | struct node *n_ptr = tipc_node_find(orig); |
| 173 | int link_up; | 198 | int link_fully_up; |
| 199 | |||
| 174 | dbg(" in own cluster\n"); | 200 | dbg(" in own cluster\n"); |
| 175 | if (n_ptr == NULL) { | 201 | if (n_ptr == NULL) { |
| 176 | n_ptr = tipc_node_create(orig); | 202 | n_ptr = tipc_node_create(orig); |
| @@ -190,14 +216,19 @@ void tipc_disc_recv_msg(struct sk_buff *buf) | |||
| 190 | } | 216 | } |
| 191 | addr = &link->media_addr; | 217 | addr = &link->media_addr; |
| 192 | if (memcmp(addr, &media_addr, sizeof(*addr))) { | 218 | if (memcmp(addr, &media_addr, sizeof(*addr))) { |
| 219 | if (tipc_link_is_up(link) || (!link->started)) { | ||
| 220 | disc_dupl_alert(b_ptr, orig, &media_addr); | ||
| 221 | spin_unlock_bh(&n_ptr->lock); | ||
| 222 | return; | ||
| 223 | } | ||
| 193 | warn("Resetting link <%s>, peer interface address changed\n", | 224 | warn("Resetting link <%s>, peer interface address changed\n", |
| 194 | link->name); | 225 | link->name); |
| 195 | memcpy(addr, &media_addr, sizeof(*addr)); | 226 | memcpy(addr, &media_addr, sizeof(*addr)); |
| 196 | tipc_link_reset(link); | 227 | tipc_link_reset(link); |
| 197 | } | 228 | } |
| 198 | link_up = tipc_link_is_up(link); | 229 | link_fully_up = (link->state == WORKING_WORKING); |
| 199 | spin_unlock_bh(&n_ptr->lock); | 230 | spin_unlock_bh(&n_ptr->lock); |
| 200 | if ((type == DSC_RESP_MSG) || link_up) | 231 | if ((type == DSC_RESP_MSG) || link_fully_up) |
| 201 | return; | 232 | return; |
| 202 | rbuf = tipc_disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr); | 233 | rbuf = tipc_disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr); |
| 203 | if (rbuf != NULL) { | 234 | if (rbuf != NULL) { |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 53bc8cb5adbc..1bb983c8130b 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
| @@ -132,7 +132,7 @@ static void link_print(struct link *l_ptr, struct print_buf *buf, | |||
| 132 | * allow the output from multiple links to be intermixed. For this reason | 132 | * allow the output from multiple links to be intermixed. For this reason |
| 133 | * routines of the form "dbg_link_XXX()" have been created that will capture | 133 | * routines of the form "dbg_link_XXX()" have been created that will capture |
| 134 | * debug info into a link's personal print buffer, which can then be dumped | 134 | * debug info into a link's personal print buffer, which can then be dumped |
| 135 | * into the TIPC system log (LOG) upon request. | 135 | * into the TIPC system log (TIPC_LOG) upon request. |
| 136 | * | 136 | * |
| 137 | * To enable per-link debugging, use LINK_LOG_BUF_SIZE to specify the size | 137 | * To enable per-link debugging, use LINK_LOG_BUF_SIZE to specify the size |
| 138 | * of the print buffer used by each link. If LINK_LOG_BUF_SIZE is set to 0, | 138 | * 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, | |||
| 141 | * when there is only a single link in the system being debugged. | 141 | * when there is only a single link in the system being debugged. |
| 142 | * | 142 | * |
| 143 | * Notes: | 143 | * Notes: |
| 144 | * - When enabled, LINK_LOG_BUF_SIZE should be set to at least 1000 (bytes) | 144 | * - When enabled, LINK_LOG_BUF_SIZE should be set to at least TIPC_PB_MIN_SIZE |
| 145 | * - "l_ptr" must be valid when using dbg_link_XXX() macros | 145 | * - "l_ptr" must be valid when using dbg_link_XXX() macros |
| 146 | */ | 146 | */ |
| 147 | 147 | ||
| @@ -159,13 +159,13 @@ static void link_print(struct link *l_ptr, struct print_buf *buf, | |||
| 159 | 159 | ||
| 160 | static void dbg_print_link(struct link *l_ptr, const char *str) | 160 | static void dbg_print_link(struct link *l_ptr, const char *str) |
| 161 | { | 161 | { |
| 162 | if (DBG_OUTPUT) | 162 | if (DBG_OUTPUT != TIPC_NULL) |
| 163 | link_print(l_ptr, DBG_OUTPUT, str); | 163 | link_print(l_ptr, DBG_OUTPUT, str); |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | static void dbg_print_buf_chain(struct sk_buff *root_buf) | 166 | static void dbg_print_buf_chain(struct sk_buff *root_buf) |
| 167 | { | 167 | { |
| 168 | if (DBG_OUTPUT) { | 168 | if (DBG_OUTPUT != TIPC_NULL) { |
| 169 | struct sk_buff *buf = root_buf; | 169 | struct sk_buff *buf = root_buf; |
| 170 | 170 | ||
| 171 | while (buf) { | 171 | while (buf) { |
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index f0b063bcc2a9..03bd659c43ca 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c | |||
| @@ -122,7 +122,7 @@ void tipc_named_publish(struct publication *publ) | |||
| 122 | struct sk_buff *buf; | 122 | struct sk_buff *buf; |
| 123 | struct distr_item *item; | 123 | struct distr_item *item; |
| 124 | 124 | ||
| 125 | list_add(&publ->local_list, &publ_root); | 125 | list_add_tail(&publ->local_list, &publ_root); |
| 126 | publ_cnt++; | 126 | publ_cnt++; |
| 127 | 127 | ||
| 128 | buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0); | 128 | buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0); |
diff --git a/net/tipc/node.c b/net/tipc/node.c index fc6d09630ccd..886bda5e88db 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
| @@ -648,7 +648,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
| 648 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 648 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
| 649 | " (network address)"); | 649 | " (network address)"); |
| 650 | 650 | ||
| 651 | if (!tipc_nodes) | 651 | if (tipc_mode != TIPC_NET_MODE) |
| 652 | return tipc_cfg_reply_none(); | 652 | return tipc_cfg_reply_none(); |
| 653 | 653 | ||
| 654 | /* Get space for all unicast links + multicast link */ | 654 | /* Get space for all unicast links + multicast link */ |
diff --git a/net/tipc/port.c b/net/tipc/port.c index b9c8c6b9e94f..c1a1a76759b5 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c | |||
| @@ -505,8 +505,13 @@ static void port_timeout(unsigned long ref) | |||
| 505 | struct port *p_ptr = tipc_port_lock(ref); | 505 | struct port *p_ptr = tipc_port_lock(ref); |
| 506 | struct sk_buff *buf = NULL; | 506 | struct sk_buff *buf = NULL; |
| 507 | 507 | ||
| 508 | if (!p_ptr || !p_ptr->publ.connected) | 508 | if (!p_ptr) |
| 509 | return; | ||
| 510 | |||
| 511 | if (!p_ptr->publ.connected) { | ||
| 512 | tipc_port_unlock(p_ptr); | ||
| 509 | return; | 513 | return; |
| 514 | } | ||
| 510 | 515 | ||
| 511 | /* Last probe answered ? */ | 516 | /* Last probe answered ? */ |
| 512 | if (p_ptr->probing_state == PROBING) { | 517 | if (p_ptr->probing_state == PROBING) { |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index acfb852e7c98..2a6a5a6b4c12 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * net/tipc/socket.c: TIPC socket API | 2 | * net/tipc/socket.c: TIPC socket API |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2001-2006, Ericsson AB | 4 | * Copyright (c) 2001-2006, Ericsson AB |
| 5 | * Copyright (c) 2004-2005, Wind River Systems | 5 | * Copyright (c) 2004-2006, Wind River Systems |
| 6 | * All rights reserved. | 6 | * All rights reserved. |
| 7 | * | 7 | * |
| 8 | * Redistribution and use in source and binary forms, with or without | 8 | * 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, | |||
| 629 | return -ENOTCONN; | 629 | return -ENOTCONN; |
| 630 | } | 630 | } |
| 631 | 631 | ||
| 632 | if (unlikely(m->msg_name)) | ||
| 633 | return -EISCONN; | ||
| 634 | |||
| 632 | /* | 635 | /* |
| 633 | * Send each iovec entry using one or more messages | 636 | * Send each iovec entry using one or more messages |
| 634 | * | 637 | * |
| @@ -641,6 +644,8 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, | |||
| 641 | curr_iovlen = m->msg_iovlen; | 644 | curr_iovlen = m->msg_iovlen; |
| 642 | my_msg.msg_iov = &my_iov; | 645 | my_msg.msg_iov = &my_iov; |
| 643 | my_msg.msg_iovlen = 1; | 646 | my_msg.msg_iovlen = 1; |
| 647 | my_msg.msg_flags = m->msg_flags; | ||
| 648 | my_msg.msg_name = NULL; | ||
| 644 | bytes_sent = 0; | 649 | bytes_sent = 0; |
| 645 | 650 | ||
| 646 | while (curr_iovlen--) { | 651 | while (curr_iovlen--) { |
| @@ -1203,7 +1208,8 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf) | |||
| 1203 | atomic_inc(&tipc_queue_size); | 1208 | atomic_inc(&tipc_queue_size); |
| 1204 | skb_queue_tail(&sock->sk->sk_receive_queue, buf); | 1209 | skb_queue_tail(&sock->sk->sk_receive_queue, buf); |
| 1205 | 1210 | ||
| 1206 | wake_up_interruptible(sock->sk->sk_sleep); | 1211 | if (waitqueue_active(sock->sk->sk_sleep)) |
| 1212 | wake_up_interruptible(sock->sk->sk_sleep); | ||
| 1207 | return TIPC_OK; | 1213 | return TIPC_OK; |
| 1208 | } | 1214 | } |
| 1209 | 1215 | ||
| @@ -1218,7 +1224,8 @@ static void wakeupdispatch(struct tipc_port *tport) | |||
| 1218 | { | 1224 | { |
| 1219 | struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle; | 1225 | struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle; |
| 1220 | 1226 | ||
| 1221 | wake_up_interruptible(tsock->sk.sk_sleep); | 1227 | if (waitqueue_active(tsock->sk.sk_sleep)) |
| 1228 | wake_up_interruptible(tsock->sk.sk_sleep); | ||
| 1222 | } | 1229 | } |
| 1223 | 1230 | ||
| 1224 | /** | 1231 | /** |
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index c51600ba5f4a..7a918f12a5df 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c | |||
| @@ -155,7 +155,7 @@ void tipc_subscr_report_overlap(struct subscription *sub, | |||
| 155 | sub->seq.upper, found_lower, found_upper); | 155 | sub->seq.upper, found_lower, found_upper); |
| 156 | if (!tipc_subscr_overlap(sub, found_lower, found_upper)) | 156 | if (!tipc_subscr_overlap(sub, found_lower, found_upper)) |
| 157 | return; | 157 | return; |
| 158 | if (!must && (sub->filter != TIPC_SUB_PORTS)) | 158 | if (!must && !(sub->filter & TIPC_SUB_PORTS)) |
| 159 | return; | 159 | return; |
| 160 | subscr_send_event(sub, found_lower, found_upper, event, port_ref, node); | 160 | subscr_send_event(sub, found_lower, found_upper, event, port_ref, node); |
| 161 | } | 161 | } |
| @@ -176,6 +176,13 @@ static void subscr_timeout(struct subscription *sub) | |||
| 176 | if (subscriber == NULL) | 176 | if (subscriber == NULL) |
| 177 | return; | 177 | return; |
| 178 | 178 | ||
| 179 | /* Validate timeout (in case subscription is being cancelled) */ | ||
| 180 | |||
| 181 | if (sub->timeout == TIPC_WAIT_FOREVER) { | ||
| 182 | tipc_ref_unlock(subscriber_ref); | ||
| 183 | return; | ||
| 184 | } | ||
| 185 | |||
| 179 | /* Unlink subscription from name table */ | 186 | /* Unlink subscription from name table */ |
| 180 | 187 | ||
| 181 | tipc_nametbl_unsubscribe(sub); | 188 | tipc_nametbl_unsubscribe(sub); |
| @@ -199,6 +206,20 @@ static void subscr_timeout(struct subscription *sub) | |||
| 199 | } | 206 | } |
| 200 | 207 | ||
| 201 | /** | 208 | /** |
| 209 | * subscr_del - delete a subscription within a subscription list | ||
| 210 | * | ||
| 211 | * Called with subscriber locked. | ||
| 212 | */ | ||
| 213 | |||
| 214 | static void subscr_del(struct subscription *sub) | ||
| 215 | { | ||
| 216 | tipc_nametbl_unsubscribe(sub); | ||
| 217 | list_del(&sub->subscription_list); | ||
| 218 | kfree(sub); | ||
| 219 | atomic_dec(&topsrv.subscription_count); | ||
| 220 | } | ||
| 221 | |||
| 222 | /** | ||
| 202 | * subscr_terminate - terminate communication with a subscriber | 223 | * subscr_terminate - terminate communication with a subscriber |
| 203 | * | 224 | * |
| 204 | * Called with subscriber locked. Routine must temporarily release this lock | 225 | * Called with subscriber locked. Routine must temporarily release this lock |
| @@ -227,12 +248,9 @@ static void subscr_terminate(struct subscriber *subscriber) | |||
| 227 | k_cancel_timer(&sub->timer); | 248 | k_cancel_timer(&sub->timer); |
| 228 | k_term_timer(&sub->timer); | 249 | k_term_timer(&sub->timer); |
| 229 | } | 250 | } |
| 230 | tipc_nametbl_unsubscribe(sub); | 251 | dbg("Term: Removing sub %u,%u,%u from subscriber %x list\n", |
| 231 | list_del(&sub->subscription_list); | ||
| 232 | dbg("Term: Removed sub %u,%u,%u from subscriber %x list\n", | ||
| 233 | sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); | 252 | sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); |
| 234 | kfree(sub); | 253 | subscr_del(sub); |
| 235 | atomic_dec(&topsrv.subscription_count); | ||
| 236 | } | 254 | } |
| 237 | 255 | ||
| 238 | /* Sever connection to subscriber */ | 256 | /* Sever connection to subscriber */ |
| @@ -253,6 +271,49 @@ static void subscr_terminate(struct subscriber *subscriber) | |||
| 253 | } | 271 | } |
| 254 | 272 | ||
| 255 | /** | 273 | /** |
| 274 | * subscr_cancel - handle subscription cancellation request | ||
| 275 | * | ||
| 276 | * Called with subscriber locked. Routine must temporarily release this lock | ||
| 277 | * to enable the subscription timeout routine to finish without deadlocking; | ||
| 278 | * the lock is then reclaimed to allow caller to release it upon return. | ||
| 279 | * | ||
| 280 | * Note that fields of 's' use subscriber's endianness! | ||
| 281 | */ | ||
| 282 | |||
| 283 | static void subscr_cancel(struct tipc_subscr *s, | ||
| 284 | struct subscriber *subscriber) | ||
| 285 | { | ||
| 286 | struct subscription *sub; | ||
| 287 | struct subscription *sub_temp; | ||
| 288 | int found = 0; | ||
| 289 | |||
| 290 | /* Find first matching subscription, exit if not found */ | ||
| 291 | |||
| 292 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, | ||
| 293 | subscription_list) { | ||
| 294 | if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) { | ||
| 295 | found = 1; | ||
| 296 | break; | ||
| 297 | } | ||
| 298 | } | ||
| 299 | if (!found) | ||
| 300 | return; | ||
| 301 | |||
| 302 | /* Cancel subscription timer (if used), then delete subscription */ | ||
| 303 | |||
| 304 | if (sub->timeout != TIPC_WAIT_FOREVER) { | ||
| 305 | sub->timeout = TIPC_WAIT_FOREVER; | ||
| 306 | spin_unlock_bh(subscriber->lock); | ||
| 307 | k_cancel_timer(&sub->timer); | ||
| 308 | k_term_timer(&sub->timer); | ||
| 309 | spin_lock_bh(subscriber->lock); | ||
| 310 | } | ||
| 311 | dbg("Cancel: removing sub %u,%u,%u from subscriber %x list\n", | ||
| 312 | sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); | ||
| 313 | subscr_del(sub); | ||
| 314 | } | ||
| 315 | |||
| 316 | /** | ||
| 256 | * subscr_subscribe - create subscription for subscriber | 317 | * subscr_subscribe - create subscription for subscriber |
| 257 | * | 318 | * |
| 258 | * Called with subscriber locked | 319 | * Called with subscriber locked |
| @@ -263,6 +324,21 @@ static void subscr_subscribe(struct tipc_subscr *s, | |||
| 263 | { | 324 | { |
| 264 | struct subscription *sub; | 325 | struct subscription *sub; |
| 265 | 326 | ||
| 327 | /* Determine/update subscriber's endianness */ | ||
| 328 | |||
| 329 | if (s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE)) | ||
| 330 | subscriber->swap = 0; | ||
| 331 | else | ||
| 332 | subscriber->swap = 1; | ||
| 333 | |||
| 334 | /* Detect & process a subscription cancellation request */ | ||
| 335 | |||
| 336 | if (s->filter & htohl(TIPC_SUB_CANCEL, subscriber->swap)) { | ||
| 337 | s->filter &= ~htohl(TIPC_SUB_CANCEL, subscriber->swap); | ||
| 338 | subscr_cancel(s, subscriber); | ||
| 339 | return; | ||
| 340 | } | ||
| 341 | |||
| 266 | /* Refuse subscription if global limit exceeded */ | 342 | /* Refuse subscription if global limit exceeded */ |
| 267 | 343 | ||
| 268 | if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) { | 344 | if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) { |
| @@ -281,13 +357,6 @@ static void subscr_subscribe(struct tipc_subscr *s, | |||
| 281 | return; | 357 | return; |
| 282 | } | 358 | } |
| 283 | 359 | ||
| 284 | /* Determine/update subscriber's endianness */ | ||
| 285 | |||
| 286 | if ((s->filter == TIPC_SUB_PORTS) || (s->filter == TIPC_SUB_SERVICE)) | ||
| 287 | subscriber->swap = 0; | ||
| 288 | else | ||
| 289 | subscriber->swap = 1; | ||
| 290 | |||
| 291 | /* Initialize subscription object */ | 360 | /* Initialize subscription object */ |
| 292 | 361 | ||
| 293 | memset(sub, 0, sizeof(*sub)); | 362 | memset(sub, 0, sizeof(*sub)); |
| @@ -296,8 +365,8 @@ static void subscr_subscribe(struct tipc_subscr *s, | |||
| 296 | sub->seq.upper = htohl(s->seq.upper, subscriber->swap); | 365 | sub->seq.upper = htohl(s->seq.upper, subscriber->swap); |
| 297 | sub->timeout = htohl(s->timeout, subscriber->swap); | 366 | sub->timeout = htohl(s->timeout, subscriber->swap); |
| 298 | sub->filter = htohl(s->filter, subscriber->swap); | 367 | sub->filter = htohl(s->filter, subscriber->swap); |
| 299 | if ((((sub->filter != TIPC_SUB_PORTS) | 368 | if ((!(sub->filter & TIPC_SUB_PORTS) |
| 300 | && (sub->filter != TIPC_SUB_SERVICE))) | 369 | == !(sub->filter & TIPC_SUB_SERVICE)) |
| 301 | || (sub->seq.lower > sub->seq.upper)) { | 370 | || (sub->seq.lower > sub->seq.upper)) { |
| 302 | warn("Subscription rejected, illegal request\n"); | 371 | warn("Subscription rejected, illegal request\n"); |
| 303 | kfree(sub); | 372 | kfree(sub); |
