diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/bcast.c | 16 | ||||
-rw-r--r-- | net/tipc/bearer.c | 18 | ||||
-rw-r--r-- | net/tipc/bearer.h | 10 | ||||
-rw-r--r-- | net/tipc/core.c | 7 | ||||
-rw-r--r-- | net/tipc/core.h | 28 | ||||
-rw-r--r-- | net/tipc/eth_media.c | 68 | ||||
-rw-r--r-- | net/tipc/handler.c | 11 | ||||
-rw-r--r-- | net/tipc/ib_media.c | 58 | ||||
-rw-r--r-- | net/tipc/link.c | 494 | ||||
-rw-r--r-- | net/tipc/link.h | 24 | ||||
-rw-r--r-- | net/tipc/msg.c | 27 | ||||
-rw-r--r-- | net/tipc/msg.h | 15 | ||||
-rw-r--r-- | net/tipc/netlink.c | 11 | ||||
-rw-r--r-- | net/tipc/node.c | 7 | ||||
-rw-r--r-- | net/tipc/node.h | 6 | ||||
-rw-r--r-- | net/tipc/port.c | 111 | ||||
-rw-r--r-- | net/tipc/port.h | 22 | ||||
-rw-r--r-- | net/tipc/socket.c | 64 |
18 files changed, 408 insertions, 589 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 716de1ac6cb5..0d4402587fdf 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
@@ -480,18 +480,24 @@ receive: | |||
480 | tipc_node_unlock(node); | 480 | tipc_node_unlock(node); |
481 | tipc_link_recv_bundle(buf); | 481 | tipc_link_recv_bundle(buf); |
482 | } else if (msg_user(msg) == MSG_FRAGMENTER) { | 482 | } else if (msg_user(msg) == MSG_FRAGMENTER) { |
483 | int ret = tipc_link_recv_fragment(&node->bclink.defragm, | 483 | int ret; |
484 | &buf, &msg); | 484 | ret = tipc_link_recv_fragment(&node->bclink.reasm_head, |
485 | if (ret < 0) | 485 | &node->bclink.reasm_tail, |
486 | &buf); | ||
487 | if (ret == LINK_REASM_ERROR) | ||
486 | goto unlock; | 488 | goto unlock; |
487 | spin_lock_bh(&bc_lock); | 489 | spin_lock_bh(&bc_lock); |
488 | bclink_accept_pkt(node, seqno); | 490 | bclink_accept_pkt(node, seqno); |
489 | bcl->stats.recv_fragments++; | 491 | bcl->stats.recv_fragments++; |
490 | if (ret > 0) | 492 | if (ret == LINK_REASM_COMPLETE) { |
491 | bcl->stats.recv_fragmented++; | 493 | bcl->stats.recv_fragmented++; |
494 | /* Point msg to inner header */ | ||
495 | msg = buf_msg(buf); | ||
496 | spin_unlock_bh(&bc_lock); | ||
497 | goto receive; | ||
498 | } | ||
492 | spin_unlock_bh(&bc_lock); | 499 | spin_unlock_bh(&bc_lock); |
493 | tipc_node_unlock(node); | 500 | tipc_node_unlock(node); |
494 | tipc_net_route_msg(buf); | ||
495 | } else if (msg_user(msg) == NAME_DISTRIBUTOR) { | 501 | } else if (msg_user(msg) == NAME_DISTRIBUTOR) { |
496 | spin_lock_bh(&bc_lock); | 502 | spin_lock_bh(&bc_lock); |
497 | bclink_accept_pkt(node, seqno); | 503 | bclink_accept_pkt(node, seqno); |
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 609c30c80816..3f9707a16d06 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
@@ -387,7 +387,7 @@ restart: | |||
387 | 387 | ||
388 | b_ptr = &tipc_bearers[bearer_id]; | 388 | b_ptr = &tipc_bearers[bearer_id]; |
389 | strcpy(b_ptr->name, name); | 389 | strcpy(b_ptr->name, name); |
390 | res = m_ptr->enable_bearer(b_ptr); | 390 | res = m_ptr->enable_media(b_ptr); |
391 | if (res) { | 391 | if (res) { |
392 | pr_warn("Bearer <%s> rejected, enable failure (%d)\n", | 392 | pr_warn("Bearer <%s> rejected, enable failure (%d)\n", |
393 | name, -res); | 393 | name, -res); |
@@ -420,23 +420,15 @@ exit: | |||
420 | } | 420 | } |
421 | 421 | ||
422 | /** | 422 | /** |
423 | * tipc_block_bearer - Block the bearer with the given name, and reset all its links | 423 | * tipc_block_bearer - Block the bearer, and reset all its links |
424 | */ | 424 | */ |
425 | int tipc_block_bearer(const char *name) | 425 | int tipc_block_bearer(struct tipc_bearer *b_ptr) |
426 | { | 426 | { |
427 | struct tipc_bearer *b_ptr = NULL; | ||
428 | struct tipc_link *l_ptr; | 427 | struct tipc_link *l_ptr; |
429 | struct tipc_link *temp_l_ptr; | 428 | struct tipc_link *temp_l_ptr; |
430 | 429 | ||
431 | read_lock_bh(&tipc_net_lock); | 430 | read_lock_bh(&tipc_net_lock); |
432 | b_ptr = tipc_bearer_find(name); | 431 | pr_info("Blocking bearer <%s>\n", b_ptr->name); |
433 | if (!b_ptr) { | ||
434 | pr_warn("Attempt to block unknown bearer <%s>\n", name); | ||
435 | read_unlock_bh(&tipc_net_lock); | ||
436 | return -EINVAL; | ||
437 | } | ||
438 | |||
439 | pr_info("Blocking bearer <%s>\n", name); | ||
440 | spin_lock_bh(&b_ptr->lock); | 432 | spin_lock_bh(&b_ptr->lock); |
441 | b_ptr->blocked = 1; | 433 | b_ptr->blocked = 1; |
442 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | 434 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { |
@@ -465,7 +457,7 @@ static void bearer_disable(struct tipc_bearer *b_ptr) | |||
465 | pr_info("Disabling bearer <%s>\n", b_ptr->name); | 457 | pr_info("Disabling bearer <%s>\n", b_ptr->name); |
466 | spin_lock_bh(&b_ptr->lock); | 458 | spin_lock_bh(&b_ptr->lock); |
467 | b_ptr->blocked = 1; | 459 | b_ptr->blocked = 1; |
468 | b_ptr->media->disable_bearer(b_ptr); | 460 | b_ptr->media->disable_media(b_ptr); |
469 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | 461 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { |
470 | tipc_link_delete(l_ptr); | 462 | tipc_link_delete(l_ptr); |
471 | } | 463 | } |
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 09c869adcfcf..e5e04be6fffa 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h | |||
@@ -75,8 +75,8 @@ struct tipc_bearer; | |||
75 | /** | 75 | /** |
76 | * struct tipc_media - TIPC media information available to internal users | 76 | * struct tipc_media - TIPC media information available to internal users |
77 | * @send_msg: routine which handles buffer transmission | 77 | * @send_msg: routine which handles buffer transmission |
78 | * @enable_bearer: routine which enables a bearer | 78 | * @enable_media: routine which enables a media |
79 | * @disable_bearer: routine which disables a bearer | 79 | * @disable_media: routine which disables a media |
80 | * @addr2str: routine which converts media address to string | 80 | * @addr2str: routine which converts media address to string |
81 | * @addr2msg: routine which converts media address to protocol message area | 81 | * @addr2msg: routine which converts media address to protocol message area |
82 | * @msg2addr: routine which converts media address from protocol message area | 82 | * @msg2addr: routine which converts media address from protocol message area |
@@ -91,8 +91,8 @@ struct tipc_media { | |||
91 | int (*send_msg)(struct sk_buff *buf, | 91 | int (*send_msg)(struct sk_buff *buf, |
92 | struct tipc_bearer *b_ptr, | 92 | struct tipc_bearer *b_ptr, |
93 | struct tipc_media_addr *dest); | 93 | struct tipc_media_addr *dest); |
94 | int (*enable_bearer)(struct tipc_bearer *b_ptr); | 94 | int (*enable_media)(struct tipc_bearer *b_ptr); |
95 | void (*disable_bearer)(struct tipc_bearer *b_ptr); | 95 | void (*disable_media)(struct tipc_bearer *b_ptr); |
96 | int (*addr2str)(struct tipc_media_addr *a, char *str_buf, int str_size); | 96 | int (*addr2str)(struct tipc_media_addr *a, char *str_buf, int str_size); |
97 | int (*addr2msg)(struct tipc_media_addr *a, char *msg_area); | 97 | int (*addr2msg)(struct tipc_media_addr *a, char *msg_area); |
98 | int (*msg2addr)(const struct tipc_bearer *b_ptr, | 98 | int (*msg2addr)(const struct tipc_bearer *b_ptr, |
@@ -163,7 +163,7 @@ int tipc_register_media(struct tipc_media *m_ptr); | |||
163 | 163 | ||
164 | void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr); | 164 | void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr); |
165 | 165 | ||
166 | int tipc_block_bearer(const char *name); | 166 | int tipc_block_bearer(struct tipc_bearer *b_ptr); |
167 | void tipc_continue(struct tipc_bearer *tb_ptr); | 167 | void tipc_continue(struct tipc_bearer *tb_ptr); |
168 | 168 | ||
169 | int tipc_enable_bearer(const char *bearer_name, u32 disc_domain, u32 priority); | 169 | int tipc_enable_bearer(const char *bearer_name, u32 disc_domain, u32 priority); |
diff --git a/net/tipc/core.c b/net/tipc/core.c index fd4eeeaa972a..c6d3f75a9e1b 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
@@ -113,7 +113,6 @@ err: | |||
113 | static void tipc_core_stop(void) | 113 | static void tipc_core_stop(void) |
114 | { | 114 | { |
115 | tipc_netlink_stop(); | 115 | tipc_netlink_stop(); |
116 | tipc_handler_stop(); | ||
117 | tipc_cfg_stop(); | 116 | tipc_cfg_stop(); |
118 | tipc_subscr_stop(); | 117 | tipc_subscr_stop(); |
119 | tipc_nametbl_stop(); | 118 | tipc_nametbl_stop(); |
@@ -146,9 +145,10 @@ static int tipc_core_start(void) | |||
146 | res = tipc_subscr_start(); | 145 | res = tipc_subscr_start(); |
147 | if (!res) | 146 | if (!res) |
148 | res = tipc_cfg_init(); | 147 | res = tipc_cfg_init(); |
149 | if (res) | 148 | if (res) { |
149 | tipc_handler_stop(); | ||
150 | tipc_core_stop(); | 150 | tipc_core_stop(); |
151 | 151 | } | |
152 | return res; | 152 | return res; |
153 | } | 153 | } |
154 | 154 | ||
@@ -178,6 +178,7 @@ static int __init tipc_init(void) | |||
178 | 178 | ||
179 | static void __exit tipc_exit(void) | 179 | static void __exit tipc_exit(void) |
180 | { | 180 | { |
181 | tipc_handler_stop(); | ||
181 | tipc_core_stop_net(); | 182 | tipc_core_stop_net(); |
182 | tipc_core_stop(); | 183 | tipc_core_stop(); |
183 | pr_info("Deactivated\n"); | 184 | pr_info("Deactivated\n"); |
diff --git a/net/tipc/core.h b/net/tipc/core.h index be72f8cebc53..94895d4e86ab 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h | |||
@@ -90,21 +90,21 @@ extern int tipc_random __read_mostly; | |||
90 | /* | 90 | /* |
91 | * Routines available to privileged subsystems | 91 | * Routines available to privileged subsystems |
92 | */ | 92 | */ |
93 | extern int tipc_core_start_net(unsigned long); | 93 | int tipc_core_start_net(unsigned long); |
94 | extern int tipc_handler_start(void); | 94 | int tipc_handler_start(void); |
95 | extern void tipc_handler_stop(void); | 95 | void tipc_handler_stop(void); |
96 | extern int tipc_netlink_start(void); | 96 | int tipc_netlink_start(void); |
97 | extern void tipc_netlink_stop(void); | 97 | void tipc_netlink_stop(void); |
98 | extern int tipc_socket_init(void); | 98 | int tipc_socket_init(void); |
99 | extern void tipc_socket_stop(void); | 99 | void tipc_socket_stop(void); |
100 | extern int tipc_sock_create_local(int type, struct socket **res); | 100 | int tipc_sock_create_local(int type, struct socket **res); |
101 | extern void tipc_sock_release_local(struct socket *sock); | 101 | void tipc_sock_release_local(struct socket *sock); |
102 | extern int tipc_sock_accept_local(struct socket *sock, | 102 | int tipc_sock_accept_local(struct socket *sock, struct socket **newsock, |
103 | struct socket **newsock, int flags); | 103 | int flags); |
104 | 104 | ||
105 | #ifdef CONFIG_SYSCTL | 105 | #ifdef CONFIG_SYSCTL |
106 | extern int tipc_register_sysctl(void); | 106 | int tipc_register_sysctl(void); |
107 | extern void tipc_unregister_sysctl(void); | 107 | void tipc_unregister_sysctl(void); |
108 | #else | 108 | #else |
109 | #define tipc_register_sysctl() 0 | 109 | #define tipc_register_sysctl() 0 |
110 | #define tipc_unregister_sysctl() | 110 | #define tipc_unregister_sysctl() |
@@ -201,6 +201,6 @@ static inline struct tipc_msg *buf_msg(struct sk_buff *skb) | |||
201 | return (struct tipc_msg *)skb->data; | 201 | return (struct tipc_msg *)skb->data; |
202 | } | 202 | } |
203 | 203 | ||
204 | extern struct sk_buff *tipc_buf_acquire(u32 size); | 204 | struct sk_buff *tipc_buf_acquire(u32 size); |
205 | 205 | ||
206 | #endif | 206 | #endif |
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c index 40ea40cf6204..f80d59f5a161 100644 --- a/net/tipc/eth_media.c +++ b/net/tipc/eth_media.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * net/tipc/eth_media.c: Ethernet bearer support for TIPC | 2 | * net/tipc/eth_media.c: Ethernet bearer support for TIPC |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2007, Ericsson AB | 4 | * Copyright (c) 2001-2007, Ericsson AB |
5 | * Copyright (c) 2005-2008, 2011, Wind River Systems | 5 | * Copyright (c) 2005-2008, 2011-2013, 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,19 +37,19 @@ | |||
37 | #include "core.h" | 37 | #include "core.h" |
38 | #include "bearer.h" | 38 | #include "bearer.h" |
39 | 39 | ||
40 | #define MAX_ETH_BEARERS MAX_BEARERS | 40 | #define MAX_ETH_MEDIA MAX_BEARERS |
41 | 41 | ||
42 | #define ETH_ADDR_OFFSET 4 /* message header offset of MAC address */ | 42 | #define ETH_ADDR_OFFSET 4 /* message header offset of MAC address */ |
43 | 43 | ||
44 | /** | 44 | /** |
45 | * struct eth_bearer - Ethernet bearer data structure | 45 | * struct eth_media - Ethernet bearer data structure |
46 | * @bearer: ptr to associated "generic" bearer structure | 46 | * @bearer: ptr to associated "generic" bearer structure |
47 | * @dev: ptr to associated Ethernet network device | 47 | * @dev: ptr to associated Ethernet network device |
48 | * @tipc_packet_type: used in binding TIPC to Ethernet driver | 48 | * @tipc_packet_type: used in binding TIPC to Ethernet driver |
49 | * @setup: work item used when enabling bearer | 49 | * @setup: work item used when enabling bearer |
50 | * @cleanup: work item used when disabling bearer | 50 | * @cleanup: work item used when disabling bearer |
51 | */ | 51 | */ |
52 | struct eth_bearer { | 52 | struct eth_media { |
53 | struct tipc_bearer *bearer; | 53 | struct tipc_bearer *bearer; |
54 | struct net_device *dev; | 54 | struct net_device *dev; |
55 | struct packet_type tipc_packet_type; | 55 | struct packet_type tipc_packet_type; |
@@ -58,7 +58,7 @@ struct eth_bearer { | |||
58 | }; | 58 | }; |
59 | 59 | ||
60 | static struct tipc_media eth_media_info; | 60 | static struct tipc_media eth_media_info; |
61 | static struct eth_bearer eth_bearers[MAX_ETH_BEARERS]; | 61 | static struct eth_media eth_media_array[MAX_ETH_MEDIA]; |
62 | static int eth_started; | 62 | static int eth_started; |
63 | 63 | ||
64 | static int recv_notification(struct notifier_block *nb, unsigned long evt, | 64 | static int recv_notification(struct notifier_block *nb, unsigned long evt, |
@@ -100,7 +100,7 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr, | |||
100 | if (!clone) | 100 | if (!clone) |
101 | return 0; | 101 | return 0; |
102 | 102 | ||
103 | dev = ((struct eth_bearer *)(tb_ptr->usr_handle))->dev; | 103 | dev = ((struct eth_media *)(tb_ptr->usr_handle))->dev; |
104 | delta = dev->hard_header_len - skb_headroom(buf); | 104 | delta = dev->hard_header_len - skb_headroom(buf); |
105 | 105 | ||
106 | if ((delta > 0) && | 106 | if ((delta > 0) && |
@@ -128,43 +128,43 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr, | |||
128 | static int recv_msg(struct sk_buff *buf, struct net_device *dev, | 128 | static int recv_msg(struct sk_buff *buf, struct net_device *dev, |
129 | struct packet_type *pt, struct net_device *orig_dev) | 129 | struct packet_type *pt, struct net_device *orig_dev) |
130 | { | 130 | { |
131 | struct eth_bearer *eb_ptr = (struct eth_bearer *)pt->af_packet_priv; | 131 | struct eth_media *eb_ptr = (struct eth_media *)pt->af_packet_priv; |
132 | 132 | ||
133 | if (!net_eq(dev_net(dev), &init_net)) { | 133 | if (!net_eq(dev_net(dev), &init_net)) { |
134 | kfree_skb(buf); | 134 | kfree_skb(buf); |
135 | return 0; | 135 | return NET_RX_DROP; |
136 | } | 136 | } |
137 | 137 | ||
138 | if (likely(eb_ptr->bearer)) { | 138 | if (likely(eb_ptr->bearer)) { |
139 | if (likely(buf->pkt_type <= PACKET_BROADCAST)) { | 139 | if (likely(buf->pkt_type <= PACKET_BROADCAST)) { |
140 | buf->next = NULL; | 140 | buf->next = NULL; |
141 | tipc_recv_msg(buf, eb_ptr->bearer); | 141 | tipc_recv_msg(buf, eb_ptr->bearer); |
142 | return 0; | 142 | return NET_RX_SUCCESS; |
143 | } | 143 | } |
144 | } | 144 | } |
145 | kfree_skb(buf); | 145 | kfree_skb(buf); |
146 | return 0; | 146 | return NET_RX_DROP; |
147 | } | 147 | } |
148 | 148 | ||
149 | /** | 149 | /** |
150 | * setup_bearer - setup association between Ethernet bearer and interface | 150 | * setup_media - setup association between Ethernet bearer and interface |
151 | */ | 151 | */ |
152 | static void setup_bearer(struct work_struct *work) | 152 | static void setup_media(struct work_struct *work) |
153 | { | 153 | { |
154 | struct eth_bearer *eb_ptr = | 154 | struct eth_media *eb_ptr = |
155 | container_of(work, struct eth_bearer, setup); | 155 | container_of(work, struct eth_media, setup); |
156 | 156 | ||
157 | dev_add_pack(&eb_ptr->tipc_packet_type); | 157 | dev_add_pack(&eb_ptr->tipc_packet_type); |
158 | } | 158 | } |
159 | 159 | ||
160 | /** | 160 | /** |
161 | * enable_bearer - attach TIPC bearer to an Ethernet interface | 161 | * enable_media - attach TIPC bearer to an Ethernet interface |
162 | */ | 162 | */ |
163 | static int enable_bearer(struct tipc_bearer *tb_ptr) | 163 | static int enable_media(struct tipc_bearer *tb_ptr) |
164 | { | 164 | { |
165 | struct net_device *dev; | 165 | struct net_device *dev; |
166 | struct eth_bearer *eb_ptr = ð_bearers[0]; | 166 | struct eth_media *eb_ptr = ð_media_array[0]; |
167 | struct eth_bearer *stop = ð_bearers[MAX_ETH_BEARERS]; | 167 | struct eth_media *stop = ð_media_array[MAX_ETH_MEDIA]; |
168 | char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1; | 168 | char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1; |
169 | int pending_dev = 0; | 169 | int pending_dev = 0; |
170 | 170 | ||
@@ -188,7 +188,7 @@ static int enable_bearer(struct tipc_bearer *tb_ptr) | |||
188 | eb_ptr->tipc_packet_type.func = recv_msg; | 188 | eb_ptr->tipc_packet_type.func = recv_msg; |
189 | eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr; | 189 | eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr; |
190 | INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list)); | 190 | INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list)); |
191 | INIT_WORK(&eb_ptr->setup, setup_bearer); | 191 | INIT_WORK(&eb_ptr->setup, setup_media); |
192 | schedule_work(&eb_ptr->setup); | 192 | schedule_work(&eb_ptr->setup); |
193 | 193 | ||
194 | /* Associate TIPC bearer with Ethernet bearer */ | 194 | /* Associate TIPC bearer with Ethernet bearer */ |
@@ -205,14 +205,14 @@ static int enable_bearer(struct tipc_bearer *tb_ptr) | |||
205 | } | 205 | } |
206 | 206 | ||
207 | /** | 207 | /** |
208 | * cleanup_bearer - break association between Ethernet bearer and interface | 208 | * cleanup_media - break association between Ethernet bearer and interface |
209 | * | 209 | * |
210 | * This routine must be invoked from a work queue because it can sleep. | 210 | * This routine must be invoked from a work queue because it can sleep. |
211 | */ | 211 | */ |
212 | static void cleanup_bearer(struct work_struct *work) | 212 | static void cleanup_media(struct work_struct *work) |
213 | { | 213 | { |
214 | struct eth_bearer *eb_ptr = | 214 | struct eth_media *eb_ptr = |
215 | container_of(work, struct eth_bearer, cleanup); | 215 | container_of(work, struct eth_media, cleanup); |
216 | 216 | ||
217 | dev_remove_pack(&eb_ptr->tipc_packet_type); | 217 | dev_remove_pack(&eb_ptr->tipc_packet_type); |
218 | dev_put(eb_ptr->dev); | 218 | dev_put(eb_ptr->dev); |
@@ -220,18 +220,18 @@ static void cleanup_bearer(struct work_struct *work) | |||
220 | } | 220 | } |
221 | 221 | ||
222 | /** | 222 | /** |
223 | * disable_bearer - detach TIPC bearer from an Ethernet interface | 223 | * disable_media - detach TIPC bearer from an Ethernet interface |
224 | * | 224 | * |
225 | * Mark Ethernet bearer as inactive so that incoming buffers are thrown away, | 225 | * Mark Ethernet bearer as inactive so that incoming buffers are thrown away, |
226 | * then get worker thread to complete bearer cleanup. (Can't do cleanup | 226 | * then get worker thread to complete bearer cleanup. (Can't do cleanup |
227 | * here because cleanup code needs to sleep and caller holds spinlocks.) | 227 | * here because cleanup code needs to sleep and caller holds spinlocks.) |
228 | */ | 228 | */ |
229 | static void disable_bearer(struct tipc_bearer *tb_ptr) | 229 | static void disable_media(struct tipc_bearer *tb_ptr) |
230 | { | 230 | { |
231 | struct eth_bearer *eb_ptr = (struct eth_bearer *)tb_ptr->usr_handle; | 231 | struct eth_media *eb_ptr = (struct eth_media *)tb_ptr->usr_handle; |
232 | 232 | ||
233 | eb_ptr->bearer = NULL; | 233 | eb_ptr->bearer = NULL; |
234 | INIT_WORK(&eb_ptr->cleanup, cleanup_bearer); | 234 | INIT_WORK(&eb_ptr->cleanup, cleanup_media); |
235 | schedule_work(&eb_ptr->cleanup); | 235 | schedule_work(&eb_ptr->cleanup); |
236 | } | 236 | } |
237 | 237 | ||
@@ -245,8 +245,8 @@ static int recv_notification(struct notifier_block *nb, unsigned long evt, | |||
245 | void *ptr) | 245 | void *ptr) |
246 | { | 246 | { |
247 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | 247 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
248 | struct eth_bearer *eb_ptr = ð_bearers[0]; | 248 | struct eth_media *eb_ptr = ð_media_array[0]; |
249 | struct eth_bearer *stop = ð_bearers[MAX_ETH_BEARERS]; | 249 | struct eth_media *stop = ð_media_array[MAX_ETH_MEDIA]; |
250 | 250 | ||
251 | if (!net_eq(dev_net(dev), &init_net)) | 251 | if (!net_eq(dev_net(dev), &init_net)) |
252 | return NOTIFY_DONE; | 252 | return NOTIFY_DONE; |
@@ -265,17 +265,17 @@ static int recv_notification(struct notifier_block *nb, unsigned long evt, | |||
265 | if (netif_carrier_ok(dev)) | 265 | if (netif_carrier_ok(dev)) |
266 | tipc_continue(eb_ptr->bearer); | 266 | tipc_continue(eb_ptr->bearer); |
267 | else | 267 | else |
268 | tipc_block_bearer(eb_ptr->bearer->name); | 268 | tipc_block_bearer(eb_ptr->bearer); |
269 | break; | 269 | break; |
270 | case NETDEV_UP: | 270 | case NETDEV_UP: |
271 | tipc_continue(eb_ptr->bearer); | 271 | tipc_continue(eb_ptr->bearer); |
272 | break; | 272 | break; |
273 | case NETDEV_DOWN: | 273 | case NETDEV_DOWN: |
274 | tipc_block_bearer(eb_ptr->bearer->name); | 274 | tipc_block_bearer(eb_ptr->bearer); |
275 | break; | 275 | break; |
276 | case NETDEV_CHANGEMTU: | 276 | case NETDEV_CHANGEMTU: |
277 | case NETDEV_CHANGEADDR: | 277 | case NETDEV_CHANGEADDR: |
278 | tipc_block_bearer(eb_ptr->bearer->name); | 278 | tipc_block_bearer(eb_ptr->bearer); |
279 | tipc_continue(eb_ptr->bearer); | 279 | tipc_continue(eb_ptr->bearer); |
280 | break; | 280 | break; |
281 | case NETDEV_UNREGISTER: | 281 | case NETDEV_UNREGISTER: |
@@ -327,8 +327,8 @@ static int eth_msg2addr(const struct tipc_bearer *tb_ptr, | |||
327 | */ | 327 | */ |
328 | static struct tipc_media eth_media_info = { | 328 | static struct tipc_media eth_media_info = { |
329 | .send_msg = send_msg, | 329 | .send_msg = send_msg, |
330 | .enable_bearer = enable_bearer, | 330 | .enable_media = enable_media, |
331 | .disable_bearer = disable_bearer, | 331 | .disable_media = disable_media, |
332 | .addr2str = eth_addr2str, | 332 | .addr2str = eth_addr2str, |
333 | .addr2msg = eth_addr2msg, | 333 | .addr2msg = eth_addr2msg, |
334 | .msg2addr = eth_msg2addr, | 334 | .msg2addr = eth_msg2addr, |
diff --git a/net/tipc/handler.c b/net/tipc/handler.c index b36f0fcd9bdf..e4bc8a296744 100644 --- a/net/tipc/handler.c +++ b/net/tipc/handler.c | |||
@@ -56,12 +56,13 @@ unsigned int tipc_k_signal(Handler routine, unsigned long argument) | |||
56 | { | 56 | { |
57 | struct queue_item *item; | 57 | struct queue_item *item; |
58 | 58 | ||
59 | spin_lock_bh(&qitem_lock); | ||
59 | if (!handler_enabled) { | 60 | if (!handler_enabled) { |
60 | pr_err("Signal request ignored by handler\n"); | 61 | pr_err("Signal request ignored by handler\n"); |
62 | spin_unlock_bh(&qitem_lock); | ||
61 | return -ENOPROTOOPT; | 63 | return -ENOPROTOOPT; |
62 | } | 64 | } |
63 | 65 | ||
64 | spin_lock_bh(&qitem_lock); | ||
65 | item = kmem_cache_alloc(tipc_queue_item_cache, GFP_ATOMIC); | 66 | item = kmem_cache_alloc(tipc_queue_item_cache, GFP_ATOMIC); |
66 | if (!item) { | 67 | if (!item) { |
67 | pr_err("Signal queue out of memory\n"); | 68 | pr_err("Signal queue out of memory\n"); |
@@ -112,10 +113,14 @@ void tipc_handler_stop(void) | |||
112 | struct list_head *l, *n; | 113 | struct list_head *l, *n; |
113 | struct queue_item *item; | 114 | struct queue_item *item; |
114 | 115 | ||
115 | if (!handler_enabled) | 116 | spin_lock_bh(&qitem_lock); |
117 | if (!handler_enabled) { | ||
118 | spin_unlock_bh(&qitem_lock); | ||
116 | return; | 119 | return; |
117 | 120 | } | |
118 | handler_enabled = 0; | 121 | handler_enabled = 0; |
122 | spin_unlock_bh(&qitem_lock); | ||
123 | |||
119 | tasklet_kill(&tipc_tasklet); | 124 | tasklet_kill(&tipc_tasklet); |
120 | 125 | ||
121 | spin_lock_bh(&qitem_lock); | 126 | spin_lock_bh(&qitem_lock); |
diff --git a/net/tipc/ib_media.c b/net/tipc/ib_media.c index 9934a32bfa87..c13989297464 100644 --- a/net/tipc/ib_media.c +++ b/net/tipc/ib_media.c | |||
@@ -42,17 +42,17 @@ | |||
42 | #include "core.h" | 42 | #include "core.h" |
43 | #include "bearer.h" | 43 | #include "bearer.h" |
44 | 44 | ||
45 | #define MAX_IB_BEARERS MAX_BEARERS | 45 | #define MAX_IB_MEDIA MAX_BEARERS |
46 | 46 | ||
47 | /** | 47 | /** |
48 | * struct ib_bearer - Infiniband bearer data structure | 48 | * struct ib_media - Infiniband media data structure |
49 | * @bearer: ptr to associated "generic" bearer structure | 49 | * @bearer: ptr to associated "generic" bearer structure |
50 | * @dev: ptr to associated Infiniband network device | 50 | * @dev: ptr to associated Infiniband network device |
51 | * @tipc_packet_type: used in binding TIPC to Infiniband driver | 51 | * @tipc_packet_type: used in binding TIPC to Infiniband driver |
52 | * @cleanup: work item used when disabling bearer | 52 | * @cleanup: work item used when disabling bearer |
53 | */ | 53 | */ |
54 | 54 | ||
55 | struct ib_bearer { | 55 | struct ib_media { |
56 | struct tipc_bearer *bearer; | 56 | struct tipc_bearer *bearer; |
57 | struct net_device *dev; | 57 | struct net_device *dev; |
58 | struct packet_type tipc_packet_type; | 58 | struct packet_type tipc_packet_type; |
@@ -61,7 +61,7 @@ struct ib_bearer { | |||
61 | }; | 61 | }; |
62 | 62 | ||
63 | static struct tipc_media ib_media_info; | 63 | static struct tipc_media ib_media_info; |
64 | static struct ib_bearer ib_bearers[MAX_IB_BEARERS]; | 64 | static struct ib_media ib_media_array[MAX_IB_MEDIA]; |
65 | static int ib_started; | 65 | static int ib_started; |
66 | 66 | ||
67 | /** | 67 | /** |
@@ -93,7 +93,7 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr, | |||
93 | if (!clone) | 93 | if (!clone) |
94 | return 0; | 94 | return 0; |
95 | 95 | ||
96 | dev = ((struct ib_bearer *)(tb_ptr->usr_handle))->dev; | 96 | dev = ((struct ib_media *)(tb_ptr->usr_handle))->dev; |
97 | delta = dev->hard_header_len - skb_headroom(buf); | 97 | delta = dev->hard_header_len - skb_headroom(buf); |
98 | 98 | ||
99 | if ((delta > 0) && | 99 | if ((delta > 0) && |
@@ -121,43 +121,43 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr, | |||
121 | static int recv_msg(struct sk_buff *buf, struct net_device *dev, | 121 | static int recv_msg(struct sk_buff *buf, struct net_device *dev, |
122 | struct packet_type *pt, struct net_device *orig_dev) | 122 | struct packet_type *pt, struct net_device *orig_dev) |
123 | { | 123 | { |
124 | struct ib_bearer *ib_ptr = (struct ib_bearer *)pt->af_packet_priv; | 124 | struct ib_media *ib_ptr = (struct ib_media *)pt->af_packet_priv; |
125 | 125 | ||
126 | if (!net_eq(dev_net(dev), &init_net)) { | 126 | if (!net_eq(dev_net(dev), &init_net)) { |
127 | kfree_skb(buf); | 127 | kfree_skb(buf); |
128 | return 0; | 128 | return NET_RX_DROP; |
129 | } | 129 | } |
130 | 130 | ||
131 | if (likely(ib_ptr->bearer)) { | 131 | if (likely(ib_ptr->bearer)) { |
132 | if (likely(buf->pkt_type <= PACKET_BROADCAST)) { | 132 | if (likely(buf->pkt_type <= PACKET_BROADCAST)) { |
133 | buf->next = NULL; | 133 | buf->next = NULL; |
134 | tipc_recv_msg(buf, ib_ptr->bearer); | 134 | tipc_recv_msg(buf, ib_ptr->bearer); |
135 | return 0; | 135 | return NET_RX_SUCCESS; |
136 | } | 136 | } |
137 | } | 137 | } |
138 | kfree_skb(buf); | 138 | kfree_skb(buf); |
139 | return 0; | 139 | return NET_RX_DROP; |
140 | } | 140 | } |
141 | 141 | ||
142 | /** | 142 | /** |
143 | * setup_bearer - setup association between InfiniBand bearer and interface | 143 | * setup_bearer - setup association between InfiniBand bearer and interface |
144 | */ | 144 | */ |
145 | static void setup_bearer(struct work_struct *work) | 145 | static void setup_media(struct work_struct *work) |
146 | { | 146 | { |
147 | struct ib_bearer *ib_ptr = | 147 | struct ib_media *ib_ptr = |
148 | container_of(work, struct ib_bearer, setup); | 148 | container_of(work, struct ib_media, setup); |
149 | 149 | ||
150 | dev_add_pack(&ib_ptr->tipc_packet_type); | 150 | dev_add_pack(&ib_ptr->tipc_packet_type); |
151 | } | 151 | } |
152 | 152 | ||
153 | /** | 153 | /** |
154 | * enable_bearer - attach TIPC bearer to an InfiniBand interface | 154 | * enable_media - attach TIPC bearer to an InfiniBand interface |
155 | */ | 155 | */ |
156 | static int enable_bearer(struct tipc_bearer *tb_ptr) | 156 | static int enable_media(struct tipc_bearer *tb_ptr) |
157 | { | 157 | { |
158 | struct net_device *dev; | 158 | struct net_device *dev; |
159 | struct ib_bearer *ib_ptr = &ib_bearers[0]; | 159 | struct ib_media *ib_ptr = &ib_media_array[0]; |
160 | struct ib_bearer *stop = &ib_bearers[MAX_IB_BEARERS]; | 160 | struct ib_media *stop = &ib_media_array[MAX_IB_MEDIA]; |
161 | char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1; | 161 | char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1; |
162 | int pending_dev = 0; | 162 | int pending_dev = 0; |
163 | 163 | ||
@@ -181,7 +181,7 @@ static int enable_bearer(struct tipc_bearer *tb_ptr) | |||
181 | ib_ptr->tipc_packet_type.func = recv_msg; | 181 | ib_ptr->tipc_packet_type.func = recv_msg; |
182 | ib_ptr->tipc_packet_type.af_packet_priv = ib_ptr; | 182 | ib_ptr->tipc_packet_type.af_packet_priv = ib_ptr; |
183 | INIT_LIST_HEAD(&(ib_ptr->tipc_packet_type.list)); | 183 | INIT_LIST_HEAD(&(ib_ptr->tipc_packet_type.list)); |
184 | INIT_WORK(&ib_ptr->setup, setup_bearer); | 184 | INIT_WORK(&ib_ptr->setup, setup_media); |
185 | schedule_work(&ib_ptr->setup); | 185 | schedule_work(&ib_ptr->setup); |
186 | 186 | ||
187 | /* Associate TIPC bearer with InfiniBand bearer */ | 187 | /* Associate TIPC bearer with InfiniBand bearer */ |
@@ -204,8 +204,8 @@ static int enable_bearer(struct tipc_bearer *tb_ptr) | |||
204 | */ | 204 | */ |
205 | static void cleanup_bearer(struct work_struct *work) | 205 | static void cleanup_bearer(struct work_struct *work) |
206 | { | 206 | { |
207 | struct ib_bearer *ib_ptr = | 207 | struct ib_media *ib_ptr = |
208 | container_of(work, struct ib_bearer, cleanup); | 208 | container_of(work, struct ib_media, cleanup); |
209 | 209 | ||
210 | dev_remove_pack(&ib_ptr->tipc_packet_type); | 210 | dev_remove_pack(&ib_ptr->tipc_packet_type); |
211 | dev_put(ib_ptr->dev); | 211 | dev_put(ib_ptr->dev); |
@@ -213,15 +213,15 @@ static void cleanup_bearer(struct work_struct *work) | |||
213 | } | 213 | } |
214 | 214 | ||
215 | /** | 215 | /** |
216 | * disable_bearer - detach TIPC bearer from an InfiniBand interface | 216 | * disable_media - detach TIPC bearer from an InfiniBand interface |
217 | * | 217 | * |
218 | * Mark InfiniBand bearer as inactive so that incoming buffers are thrown away, | 218 | * Mark InfiniBand bearer as inactive so that incoming buffers are thrown away, |
219 | * then get worker thread to complete bearer cleanup. (Can't do cleanup | 219 | * then get worker thread to complete bearer cleanup. (Can't do cleanup |
220 | * here because cleanup code needs to sleep and caller holds spinlocks.) | 220 | * here because cleanup code needs to sleep and caller holds spinlocks.) |
221 | */ | 221 | */ |
222 | static void disable_bearer(struct tipc_bearer *tb_ptr) | 222 | static void disable_media(struct tipc_bearer *tb_ptr) |
223 | { | 223 | { |
224 | struct ib_bearer *ib_ptr = (struct ib_bearer *)tb_ptr->usr_handle; | 224 | struct ib_media *ib_ptr = (struct ib_media *)tb_ptr->usr_handle; |
225 | 225 | ||
226 | ib_ptr->bearer = NULL; | 226 | ib_ptr->bearer = NULL; |
227 | INIT_WORK(&ib_ptr->cleanup, cleanup_bearer); | 227 | INIT_WORK(&ib_ptr->cleanup, cleanup_bearer); |
@@ -238,8 +238,8 @@ static int recv_notification(struct notifier_block *nb, unsigned long evt, | |||
238 | void *ptr) | 238 | void *ptr) |
239 | { | 239 | { |
240 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | 240 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
241 | struct ib_bearer *ib_ptr = &ib_bearers[0]; | 241 | struct ib_media *ib_ptr = &ib_media_array[0]; |
242 | struct ib_bearer *stop = &ib_bearers[MAX_IB_BEARERS]; | 242 | struct ib_media *stop = &ib_media_array[MAX_IB_MEDIA]; |
243 | 243 | ||
244 | if (!net_eq(dev_net(dev), &init_net)) | 244 | if (!net_eq(dev_net(dev), &init_net)) |
245 | return NOTIFY_DONE; | 245 | return NOTIFY_DONE; |
@@ -258,17 +258,17 @@ static int recv_notification(struct notifier_block *nb, unsigned long evt, | |||
258 | if (netif_carrier_ok(dev)) | 258 | if (netif_carrier_ok(dev)) |
259 | tipc_continue(ib_ptr->bearer); | 259 | tipc_continue(ib_ptr->bearer); |
260 | else | 260 | else |
261 | tipc_block_bearer(ib_ptr->bearer->name); | 261 | tipc_block_bearer(ib_ptr->bearer); |
262 | break; | 262 | break; |
263 | case NETDEV_UP: | 263 | case NETDEV_UP: |
264 | tipc_continue(ib_ptr->bearer); | 264 | tipc_continue(ib_ptr->bearer); |
265 | break; | 265 | break; |
266 | case NETDEV_DOWN: | 266 | case NETDEV_DOWN: |
267 | tipc_block_bearer(ib_ptr->bearer->name); | 267 | tipc_block_bearer(ib_ptr->bearer); |
268 | break; | 268 | break; |
269 | case NETDEV_CHANGEMTU: | 269 | case NETDEV_CHANGEMTU: |
270 | case NETDEV_CHANGEADDR: | 270 | case NETDEV_CHANGEADDR: |
271 | tipc_block_bearer(ib_ptr->bearer->name); | 271 | tipc_block_bearer(ib_ptr->bearer); |
272 | tipc_continue(ib_ptr->bearer); | 272 | tipc_continue(ib_ptr->bearer); |
273 | break; | 273 | break; |
274 | case NETDEV_UNREGISTER: | 274 | case NETDEV_UNREGISTER: |
@@ -323,8 +323,8 @@ static int ib_msg2addr(const struct tipc_bearer *tb_ptr, | |||
323 | */ | 323 | */ |
324 | static struct tipc_media ib_media_info = { | 324 | static struct tipc_media ib_media_info = { |
325 | .send_msg = send_msg, | 325 | .send_msg = send_msg, |
326 | .enable_bearer = enable_bearer, | 326 | .enable_media = enable_media, |
327 | .disable_bearer = disable_bearer, | 327 | .disable_media = disable_media, |
328 | .addr2str = ib_addr2str, | 328 | .addr2str = ib_addr2str, |
329 | .addr2msg = ib_addr2msg, | 329 | .addr2msg = ib_addr2msg, |
330 | .msg2addr = ib_msg2addr, | 330 | .msg2addr = ib_msg2addr, |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 0cc3d9015c5d..13b987745820 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -75,20 +75,6 @@ static const char *link_unk_evt = "Unknown link event "; | |||
75 | */ | 75 | */ |
76 | #define START_CHANGEOVER 100000u | 76 | #define START_CHANGEOVER 100000u |
77 | 77 | ||
78 | /** | ||
79 | * struct tipc_link_name - deconstructed link name | ||
80 | * @addr_local: network address of node at this end | ||
81 | * @if_local: name of interface at this end | ||
82 | * @addr_peer: network address of node at far end | ||
83 | * @if_peer: name of interface at far end | ||
84 | */ | ||
85 | struct tipc_link_name { | ||
86 | u32 addr_local; | ||
87 | char if_local[TIPC_MAX_IF_NAME]; | ||
88 | u32 addr_peer; | ||
89 | char if_peer[TIPC_MAX_IF_NAME]; | ||
90 | }; | ||
91 | |||
92 | static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, | 78 | static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, |
93 | struct sk_buff *buf); | 79 | struct sk_buff *buf); |
94 | static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf); | 80 | static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf); |
@@ -97,8 +83,7 @@ static int link_recv_changeover_msg(struct tipc_link **l_ptr, | |||
97 | static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance); | 83 | static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance); |
98 | static int link_send_sections_long(struct tipc_port *sender, | 84 | static int link_send_sections_long(struct tipc_port *sender, |
99 | struct iovec const *msg_sect, | 85 | struct iovec const *msg_sect, |
100 | u32 num_sect, unsigned int total_len, | 86 | unsigned int len, u32 destnode); |
101 | u32 destnode); | ||
102 | static void link_state_event(struct tipc_link *l_ptr, u32 event); | 87 | static void link_state_event(struct tipc_link *l_ptr, u32 event); |
103 | static void link_reset_statistics(struct tipc_link *l_ptr); | 88 | static void link_reset_statistics(struct tipc_link *l_ptr); |
104 | static void link_print(struct tipc_link *l_ptr, const char *str); | 89 | static void link_print(struct tipc_link *l_ptr, const char *str); |
@@ -161,72 +146,6 @@ int tipc_link_is_active(struct tipc_link *l_ptr) | |||
161 | } | 146 | } |
162 | 147 | ||
163 | /** | 148 | /** |
164 | * link_name_validate - validate & (optionally) deconstruct tipc_link name | ||
165 | * @name: ptr to link name string | ||
166 | * @name_parts: ptr to area for link name components (or NULL if not needed) | ||
167 | * | ||
168 | * Returns 1 if link name is valid, otherwise 0. | ||
169 | */ | ||
170 | static int link_name_validate(const char *name, | ||
171 | struct tipc_link_name *name_parts) | ||
172 | { | ||
173 | char name_copy[TIPC_MAX_LINK_NAME]; | ||
174 | char *addr_local; | ||
175 | char *if_local; | ||
176 | char *addr_peer; | ||
177 | char *if_peer; | ||
178 | char dummy; | ||
179 | u32 z_local, c_local, n_local; | ||
180 | u32 z_peer, c_peer, n_peer; | ||
181 | u32 if_local_len; | ||
182 | u32 if_peer_len; | ||
183 | |||
184 | /* copy link name & ensure length is OK */ | ||
185 | name_copy[TIPC_MAX_LINK_NAME - 1] = 0; | ||
186 | /* need above in case non-Posix strncpy() doesn't pad with nulls */ | ||
187 | strncpy(name_copy, name, TIPC_MAX_LINK_NAME); | ||
188 | if (name_copy[TIPC_MAX_LINK_NAME - 1] != 0) | ||
189 | return 0; | ||
190 | |||
191 | /* ensure all component parts of link name are present */ | ||
192 | addr_local = name_copy; | ||
193 | if_local = strchr(addr_local, ':'); | ||
194 | if (if_local == NULL) | ||
195 | return 0; | ||
196 | *(if_local++) = 0; | ||
197 | addr_peer = strchr(if_local, '-'); | ||
198 | if (addr_peer == NULL) | ||
199 | return 0; | ||
200 | *(addr_peer++) = 0; | ||
201 | if_local_len = addr_peer - if_local; | ||
202 | if_peer = strchr(addr_peer, ':'); | ||
203 | if (if_peer == NULL) | ||
204 | return 0; | ||
205 | *(if_peer++) = 0; | ||
206 | if_peer_len = strlen(if_peer) + 1; | ||
207 | |||
208 | /* validate component parts of link name */ | ||
209 | if ((sscanf(addr_local, "%u.%u.%u%c", | ||
210 | &z_local, &c_local, &n_local, &dummy) != 3) || | ||
211 | (sscanf(addr_peer, "%u.%u.%u%c", | ||
212 | &z_peer, &c_peer, &n_peer, &dummy) != 3) || | ||
213 | (z_local > 255) || (c_local > 4095) || (n_local > 4095) || | ||
214 | (z_peer > 255) || (c_peer > 4095) || (n_peer > 4095) || | ||
215 | (if_local_len <= 1) || (if_local_len > TIPC_MAX_IF_NAME) || | ||
216 | (if_peer_len <= 1) || (if_peer_len > TIPC_MAX_IF_NAME)) | ||
217 | return 0; | ||
218 | |||
219 | /* return link name components, if necessary */ | ||
220 | if (name_parts) { | ||
221 | name_parts->addr_local = tipc_addr(z_local, c_local, n_local); | ||
222 | strcpy(name_parts->if_local, if_local); | ||
223 | name_parts->addr_peer = tipc_addr(z_peer, c_peer, n_peer); | ||
224 | strcpy(name_parts->if_peer, if_peer); | ||
225 | } | ||
226 | return 1; | ||
227 | } | ||
228 | |||
229 | /** | ||
230 | * link_timeout - handle expiration of link timer | 149 | * link_timeout - handle expiration of link timer |
231 | * @l_ptr: pointer to link | 150 | * @l_ptr: pointer to link |
232 | * | 151 | * |
@@ -485,15 +404,9 @@ static void link_release_outqueue(struct tipc_link *l_ptr) | |||
485 | */ | 404 | */ |
486 | void tipc_link_reset_fragments(struct tipc_link *l_ptr) | 405 | void tipc_link_reset_fragments(struct tipc_link *l_ptr) |
487 | { | 406 | { |
488 | struct sk_buff *buf = l_ptr->defragm_buf; | 407 | kfree_skb(l_ptr->reasm_head); |
489 | struct sk_buff *next; | 408 | l_ptr->reasm_head = NULL; |
490 | 409 | l_ptr->reasm_tail = NULL; | |
491 | while (buf) { | ||
492 | next = buf->next; | ||
493 | kfree_skb(buf); | ||
494 | buf = next; | ||
495 | } | ||
496 | l_ptr->defragm_buf = NULL; | ||
497 | } | 410 | } |
498 | 411 | ||
499 | /** | 412 | /** |
@@ -1065,8 +978,7 @@ static int link_send_buf_fast(struct tipc_link *l_ptr, struct sk_buff *buf, | |||
1065 | */ | 978 | */ |
1066 | int tipc_link_send_sections_fast(struct tipc_port *sender, | 979 | int tipc_link_send_sections_fast(struct tipc_port *sender, |
1067 | struct iovec const *msg_sect, | 980 | struct iovec const *msg_sect, |
1068 | const u32 num_sect, unsigned int total_len, | 981 | unsigned int len, u32 destaddr) |
1069 | u32 destaddr) | ||
1070 | { | 982 | { |
1071 | struct tipc_msg *hdr = &sender->phdr; | 983 | struct tipc_msg *hdr = &sender->phdr; |
1072 | struct tipc_link *l_ptr; | 984 | struct tipc_link *l_ptr; |
@@ -1080,8 +992,7 @@ again: | |||
1080 | * Try building message using port's max_pkt hint. | 992 | * Try building message using port's max_pkt hint. |
1081 | * (Must not hold any locks while building message.) | 993 | * (Must not hold any locks while building message.) |
1082 | */ | 994 | */ |
1083 | res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, | 995 | res = tipc_msg_build(hdr, msg_sect, len, sender->max_pkt, &buf); |
1084 | sender->max_pkt, &buf); | ||
1085 | /* Exit if build request was invalid */ | 996 | /* Exit if build request was invalid */ |
1086 | if (unlikely(res < 0)) | 997 | if (unlikely(res < 0)) |
1087 | return res; | 998 | return res; |
@@ -1121,8 +1032,7 @@ exit: | |||
1121 | if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt) | 1032 | if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt) |
1122 | goto again; | 1033 | goto again; |
1123 | 1034 | ||
1124 | return link_send_sections_long(sender, msg_sect, | 1035 | return link_send_sections_long(sender, msg_sect, len, |
1125 | num_sect, total_len, | ||
1126 | destaddr); | 1036 | destaddr); |
1127 | } | 1037 | } |
1128 | tipc_node_unlock(node); | 1038 | tipc_node_unlock(node); |
@@ -1133,8 +1043,8 @@ exit: | |||
1133 | if (buf) | 1043 | if (buf) |
1134 | return tipc_reject_msg(buf, TIPC_ERR_NO_NODE); | 1044 | return tipc_reject_msg(buf, TIPC_ERR_NO_NODE); |
1135 | if (res >= 0) | 1045 | if (res >= 0) |
1136 | return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect, | 1046 | return tipc_port_reject_sections(sender, hdr, msg_sect, |
1137 | total_len, TIPC_ERR_NO_NODE); | 1047 | len, TIPC_ERR_NO_NODE); |
1138 | return res; | 1048 | return res; |
1139 | } | 1049 | } |
1140 | 1050 | ||
@@ -1154,18 +1064,17 @@ exit: | |||
1154 | */ | 1064 | */ |
1155 | static int link_send_sections_long(struct tipc_port *sender, | 1065 | static int link_send_sections_long(struct tipc_port *sender, |
1156 | struct iovec const *msg_sect, | 1066 | struct iovec const *msg_sect, |
1157 | u32 num_sect, unsigned int total_len, | 1067 | unsigned int len, u32 destaddr) |
1158 | u32 destaddr) | ||
1159 | { | 1068 | { |
1160 | struct tipc_link *l_ptr; | 1069 | struct tipc_link *l_ptr; |
1161 | struct tipc_node *node; | 1070 | struct tipc_node *node; |
1162 | struct tipc_msg *hdr = &sender->phdr; | 1071 | struct tipc_msg *hdr = &sender->phdr; |
1163 | u32 dsz = total_len; | 1072 | u32 dsz = len; |
1164 | u32 max_pkt, fragm_sz, rest; | 1073 | u32 max_pkt, fragm_sz, rest; |
1165 | struct tipc_msg fragm_hdr; | 1074 | struct tipc_msg fragm_hdr; |
1166 | struct sk_buff *buf, *buf_chain, *prev; | 1075 | struct sk_buff *buf, *buf_chain, *prev; |
1167 | u32 fragm_crs, fragm_rest, hsz, sect_rest; | 1076 | u32 fragm_crs, fragm_rest, hsz, sect_rest; |
1168 | const unchar *sect_crs; | 1077 | const unchar __user *sect_crs; |
1169 | int curr_sect; | 1078 | int curr_sect; |
1170 | u32 fragm_no; | 1079 | u32 fragm_no; |
1171 | int res = 0; | 1080 | int res = 0; |
@@ -1207,7 +1116,7 @@ again: | |||
1207 | 1116 | ||
1208 | if (!sect_rest) { | 1117 | if (!sect_rest) { |
1209 | sect_rest = msg_sect[++curr_sect].iov_len; | 1118 | sect_rest = msg_sect[++curr_sect].iov_len; |
1210 | sect_crs = (const unchar *)msg_sect[curr_sect].iov_base; | 1119 | sect_crs = msg_sect[curr_sect].iov_base; |
1211 | } | 1120 | } |
1212 | 1121 | ||
1213 | if (sect_rest < fragm_rest) | 1122 | if (sect_rest < fragm_rest) |
@@ -1283,8 +1192,8 @@ reject: | |||
1283 | buf = buf_chain->next; | 1192 | buf = buf_chain->next; |
1284 | kfree_skb(buf_chain); | 1193 | kfree_skb(buf_chain); |
1285 | } | 1194 | } |
1286 | return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect, | 1195 | return tipc_port_reject_sections(sender, hdr, msg_sect, |
1287 | total_len, TIPC_ERR_NO_NODE); | 1196 | len, TIPC_ERR_NO_NODE); |
1288 | } | 1197 | } |
1289 | 1198 | ||
1290 | /* Append chain of fragments to send queue & send them */ | 1199 | /* Append chain of fragments to send queue & send them */ |
@@ -1589,18 +1498,19 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
1589 | int type; | 1498 | int type; |
1590 | 1499 | ||
1591 | head = head->next; | 1500 | head = head->next; |
1501 | buf->next = NULL; | ||
1592 | 1502 | ||
1593 | /* Ensure bearer is still enabled */ | 1503 | /* Ensure bearer is still enabled */ |
1594 | if (unlikely(!b_ptr->active)) | 1504 | if (unlikely(!b_ptr->active)) |
1595 | goto cont; | 1505 | goto discard; |
1596 | 1506 | ||
1597 | /* Ensure message is well-formed */ | 1507 | /* Ensure message is well-formed */ |
1598 | if (unlikely(!link_recv_buf_validate(buf))) | 1508 | if (unlikely(!link_recv_buf_validate(buf))) |
1599 | goto cont; | 1509 | goto discard; |
1600 | 1510 | ||
1601 | /* Ensure message data is a single contiguous unit */ | 1511 | /* Ensure message data is a single contiguous unit */ |
1602 | if (unlikely(skb_linearize(buf))) | 1512 | if (unlikely(skb_linearize(buf))) |
1603 | goto cont; | 1513 | goto discard; |
1604 | 1514 | ||
1605 | /* Handle arrival of a non-unicast link message */ | 1515 | /* Handle arrival of a non-unicast link message */ |
1606 | msg = buf_msg(buf); | 1516 | msg = buf_msg(buf); |
@@ -1616,20 +1526,18 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
1616 | /* Discard unicast link messages destined for another node */ | 1526 | /* Discard unicast link messages destined for another node */ |
1617 | if (unlikely(!msg_short(msg) && | 1527 | if (unlikely(!msg_short(msg) && |
1618 | (msg_destnode(msg) != tipc_own_addr))) | 1528 | (msg_destnode(msg) != tipc_own_addr))) |
1619 | goto cont; | 1529 | goto discard; |
1620 | 1530 | ||
1621 | /* Locate neighboring node that sent message */ | 1531 | /* Locate neighboring node that sent message */ |
1622 | n_ptr = tipc_node_find(msg_prevnode(msg)); | 1532 | n_ptr = tipc_node_find(msg_prevnode(msg)); |
1623 | if (unlikely(!n_ptr)) | 1533 | if (unlikely(!n_ptr)) |
1624 | goto cont; | 1534 | goto discard; |
1625 | tipc_node_lock(n_ptr); | 1535 | tipc_node_lock(n_ptr); |
1626 | 1536 | ||
1627 | /* Locate unicast link endpoint that should handle message */ | 1537 | /* Locate unicast link endpoint that should handle message */ |
1628 | l_ptr = n_ptr->links[b_ptr->identity]; | 1538 | l_ptr = n_ptr->links[b_ptr->identity]; |
1629 | if (unlikely(!l_ptr)) { | 1539 | if (unlikely(!l_ptr)) |
1630 | tipc_node_unlock(n_ptr); | 1540 | goto unlock_discard; |
1631 | goto cont; | ||
1632 | } | ||
1633 | 1541 | ||
1634 | /* Verify that communication with node is currently allowed */ | 1542 | /* Verify that communication with node is currently allowed */ |
1635 | if ((n_ptr->block_setup & WAIT_PEER_DOWN) && | 1543 | if ((n_ptr->block_setup & WAIT_PEER_DOWN) && |
@@ -1639,10 +1547,8 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
1639 | !msg_redundant_link(msg)) | 1547 | !msg_redundant_link(msg)) |
1640 | n_ptr->block_setup &= ~WAIT_PEER_DOWN; | 1548 | n_ptr->block_setup &= ~WAIT_PEER_DOWN; |
1641 | 1549 | ||
1642 | if (n_ptr->block_setup) { | 1550 | if (n_ptr->block_setup) |
1643 | tipc_node_unlock(n_ptr); | 1551 | goto unlock_discard; |
1644 | goto cont; | ||
1645 | } | ||
1646 | 1552 | ||
1647 | /* Validate message sequence number info */ | 1553 | /* Validate message sequence number info */ |
1648 | seq_no = msg_seqno(msg); | 1554 | seq_no = msg_seqno(msg); |
@@ -1678,98 +1584,100 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
1678 | 1584 | ||
1679 | /* Now (finally!) process the incoming message */ | 1585 | /* Now (finally!) process the incoming message */ |
1680 | protocol_check: | 1586 | protocol_check: |
1681 | if (likely(link_working_working(l_ptr))) { | 1587 | if (unlikely(!link_working_working(l_ptr))) { |
1682 | if (likely(seq_no == mod(l_ptr->next_in_no))) { | 1588 | if (msg_user(msg) == LINK_PROTOCOL) { |
1683 | l_ptr->next_in_no++; | 1589 | link_recv_proto_msg(l_ptr, buf); |
1684 | if (unlikely(l_ptr->oldest_deferred_in)) | 1590 | head = link_insert_deferred_queue(l_ptr, head); |
1685 | head = link_insert_deferred_queue(l_ptr, | 1591 | tipc_node_unlock(n_ptr); |
1686 | head); | 1592 | continue; |
1687 | deliver: | 1593 | } |
1688 | if (likely(msg_isdata(msg))) { | 1594 | |
1689 | tipc_node_unlock(n_ptr); | 1595 | /* Traffic message. Conditionally activate link */ |
1690 | tipc_port_recv_msg(buf); | 1596 | link_state_event(l_ptr, TRAFFIC_MSG_EVT); |
1691 | continue; | 1597 | |
1692 | } | 1598 | if (link_working_working(l_ptr)) { |
1693 | switch (msg_user(msg)) { | 1599 | /* Re-insert buffer in front of queue */ |
1694 | int ret; | 1600 | buf->next = head; |
1695 | case MSG_BUNDLER: | 1601 | head = buf; |
1696 | l_ptr->stats.recv_bundles++; | ||
1697 | l_ptr->stats.recv_bundled += | ||
1698 | msg_msgcnt(msg); | ||
1699 | tipc_node_unlock(n_ptr); | ||
1700 | tipc_link_recv_bundle(buf); | ||
1701 | continue; | ||
1702 | case NAME_DISTRIBUTOR: | ||
1703 | n_ptr->bclink.recv_permitted = true; | ||
1704 | tipc_node_unlock(n_ptr); | ||
1705 | tipc_named_recv(buf); | ||
1706 | continue; | ||
1707 | case BCAST_PROTOCOL: | ||
1708 | tipc_link_recv_sync(n_ptr, buf); | ||
1709 | tipc_node_unlock(n_ptr); | ||
1710 | continue; | ||
1711 | case CONN_MANAGER: | ||
1712 | tipc_node_unlock(n_ptr); | ||
1713 | tipc_port_recv_proto_msg(buf); | ||
1714 | continue; | ||
1715 | case MSG_FRAGMENTER: | ||
1716 | l_ptr->stats.recv_fragments++; | ||
1717 | ret = tipc_link_recv_fragment( | ||
1718 | &l_ptr->defragm_buf, | ||
1719 | &buf, &msg); | ||
1720 | if (ret == 1) { | ||
1721 | l_ptr->stats.recv_fragmented++; | ||
1722 | goto deliver; | ||
1723 | } | ||
1724 | if (ret == -1) | ||
1725 | l_ptr->next_in_no--; | ||
1726 | break; | ||
1727 | case CHANGEOVER_PROTOCOL: | ||
1728 | type = msg_type(msg); | ||
1729 | if (link_recv_changeover_msg(&l_ptr, | ||
1730 | &buf)) { | ||
1731 | msg = buf_msg(buf); | ||
1732 | seq_no = msg_seqno(msg); | ||
1733 | if (type == ORIGINAL_MSG) | ||
1734 | goto deliver; | ||
1735 | goto protocol_check; | ||
1736 | } | ||
1737 | break; | ||
1738 | default: | ||
1739 | kfree_skb(buf); | ||
1740 | buf = NULL; | ||
1741 | break; | ||
1742 | } | ||
1743 | tipc_node_unlock(n_ptr); | 1602 | tipc_node_unlock(n_ptr); |
1744 | tipc_net_route_msg(buf); | ||
1745 | continue; | 1603 | continue; |
1746 | } | 1604 | } |
1605 | goto unlock_discard; | ||
1606 | } | ||
1607 | |||
1608 | /* Link is now in state WORKING_WORKING */ | ||
1609 | if (unlikely(seq_no != mod(l_ptr->next_in_no))) { | ||
1747 | link_handle_out_of_seq_msg(l_ptr, buf); | 1610 | link_handle_out_of_seq_msg(l_ptr, buf); |
1748 | head = link_insert_deferred_queue(l_ptr, head); | 1611 | head = link_insert_deferred_queue(l_ptr, head); |
1749 | tipc_node_unlock(n_ptr); | 1612 | tipc_node_unlock(n_ptr); |
1750 | continue; | 1613 | continue; |
1751 | } | 1614 | } |
1752 | 1615 | l_ptr->next_in_no++; | |
1753 | /* Link is not in state WORKING_WORKING */ | 1616 | if (unlikely(l_ptr->oldest_deferred_in)) |
1754 | if (msg_user(msg) == LINK_PROTOCOL) { | ||
1755 | link_recv_proto_msg(l_ptr, buf); | ||
1756 | head = link_insert_deferred_queue(l_ptr, head); | 1617 | head = link_insert_deferred_queue(l_ptr, head); |
1618 | deliver: | ||
1619 | if (likely(msg_isdata(msg))) { | ||
1757 | tipc_node_unlock(n_ptr); | 1620 | tipc_node_unlock(n_ptr); |
1621 | tipc_port_recv_msg(buf); | ||
1758 | continue; | 1622 | continue; |
1759 | } | 1623 | } |
1760 | 1624 | switch (msg_user(msg)) { | |
1761 | /* Traffic message. Conditionally activate link */ | 1625 | int ret; |
1762 | link_state_event(l_ptr, TRAFFIC_MSG_EVT); | 1626 | case MSG_BUNDLER: |
1763 | 1627 | l_ptr->stats.recv_bundles++; | |
1764 | if (link_working_working(l_ptr)) { | 1628 | l_ptr->stats.recv_bundled += msg_msgcnt(msg); |
1765 | /* Re-insert buffer in front of queue */ | 1629 | tipc_node_unlock(n_ptr); |
1766 | buf->next = head; | 1630 | tipc_link_recv_bundle(buf); |
1767 | head = buf; | 1631 | continue; |
1632 | case NAME_DISTRIBUTOR: | ||
1633 | n_ptr->bclink.recv_permitted = true; | ||
1634 | tipc_node_unlock(n_ptr); | ||
1635 | tipc_named_recv(buf); | ||
1636 | continue; | ||
1637 | case BCAST_PROTOCOL: | ||
1638 | tipc_link_recv_sync(n_ptr, buf); | ||
1639 | tipc_node_unlock(n_ptr); | ||
1640 | continue; | ||
1641 | case CONN_MANAGER: | ||
1642 | tipc_node_unlock(n_ptr); | ||
1643 | tipc_port_recv_proto_msg(buf); | ||
1644 | continue; | ||
1645 | case MSG_FRAGMENTER: | ||
1646 | l_ptr->stats.recv_fragments++; | ||
1647 | ret = tipc_link_recv_fragment(&l_ptr->reasm_head, | ||
1648 | &l_ptr->reasm_tail, | ||
1649 | &buf); | ||
1650 | if (ret == LINK_REASM_COMPLETE) { | ||
1651 | l_ptr->stats.recv_fragmented++; | ||
1652 | msg = buf_msg(buf); | ||
1653 | goto deliver; | ||
1654 | } | ||
1655 | if (ret == LINK_REASM_ERROR) | ||
1656 | tipc_link_reset(l_ptr); | ||
1768 | tipc_node_unlock(n_ptr); | 1657 | tipc_node_unlock(n_ptr); |
1769 | continue; | 1658 | continue; |
1659 | case CHANGEOVER_PROTOCOL: | ||
1660 | type = msg_type(msg); | ||
1661 | if (link_recv_changeover_msg(&l_ptr, &buf)) { | ||
1662 | msg = buf_msg(buf); | ||
1663 | seq_no = msg_seqno(msg); | ||
1664 | if (type == ORIGINAL_MSG) | ||
1665 | goto deliver; | ||
1666 | goto protocol_check; | ||
1667 | } | ||
1668 | break; | ||
1669 | default: | ||
1670 | kfree_skb(buf); | ||
1671 | buf = NULL; | ||
1672 | break; | ||
1770 | } | 1673 | } |
1771 | tipc_node_unlock(n_ptr); | 1674 | tipc_node_unlock(n_ptr); |
1772 | cont: | 1675 | tipc_net_route_msg(buf); |
1676 | continue; | ||
1677 | unlock_discard: | ||
1678 | |||
1679 | tipc_node_unlock(n_ptr); | ||
1680 | discard: | ||
1773 | kfree_skb(buf); | 1681 | kfree_skb(buf); |
1774 | } | 1682 | } |
1775 | read_unlock_bh(&tipc_net_lock); | 1683 | read_unlock_bh(&tipc_net_lock); |
@@ -2432,114 +2340,48 @@ static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf) | |||
2432 | } | 2340 | } |
2433 | 2341 | ||
2434 | /* | 2342 | /* |
2435 | * A pending message being re-assembled must store certain values | ||
2436 | * to handle subsequent fragments correctly. The following functions | ||
2437 | * help storing these values in unused, available fields in the | ||
2438 | * pending message. This makes dynamic memory allocation unnecessary. | ||
2439 | */ | ||
2440 | static void set_long_msg_seqno(struct sk_buff *buf, u32 seqno) | ||
2441 | { | ||
2442 | msg_set_seqno(buf_msg(buf), seqno); | ||
2443 | } | ||
2444 | |||
2445 | static u32 get_fragm_size(struct sk_buff *buf) | ||
2446 | { | ||
2447 | return msg_ack(buf_msg(buf)); | ||
2448 | } | ||
2449 | |||
2450 | static void set_fragm_size(struct sk_buff *buf, u32 sz) | ||
2451 | { | ||
2452 | msg_set_ack(buf_msg(buf), sz); | ||
2453 | } | ||
2454 | |||
2455 | static u32 get_expected_frags(struct sk_buff *buf) | ||
2456 | { | ||
2457 | return msg_bcast_ack(buf_msg(buf)); | ||
2458 | } | ||
2459 | |||
2460 | static void set_expected_frags(struct sk_buff *buf, u32 exp) | ||
2461 | { | ||
2462 | msg_set_bcast_ack(buf_msg(buf), exp); | ||
2463 | } | ||
2464 | |||
2465 | /* | ||
2466 | * tipc_link_recv_fragment(): Called with node lock on. Returns | 2343 | * tipc_link_recv_fragment(): Called with node lock on. Returns |
2467 | * the reassembled buffer if message is complete. | 2344 | * the reassembled buffer if message is complete. |
2468 | */ | 2345 | */ |
2469 | int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, | 2346 | int tipc_link_recv_fragment(struct sk_buff **head, struct sk_buff **tail, |
2470 | struct tipc_msg **m) | 2347 | struct sk_buff **fbuf) |
2471 | { | 2348 | { |
2472 | struct sk_buff *prev = NULL; | 2349 | struct sk_buff *frag = *fbuf; |
2473 | struct sk_buff *fbuf = *fb; | 2350 | struct tipc_msg *msg = buf_msg(frag); |
2474 | struct tipc_msg *fragm = buf_msg(fbuf); | 2351 | u32 fragid = msg_type(msg); |
2475 | struct sk_buff *pbuf = *pending; | 2352 | bool headstolen; |
2476 | u32 long_msg_seq_no = msg_long_msgno(fragm); | 2353 | int delta; |
2477 | 2354 | ||
2478 | *fb = NULL; | 2355 | skb_pull(frag, msg_hdr_sz(msg)); |
2479 | 2356 | if (fragid == FIRST_FRAGMENT) { | |
2480 | /* Is there an incomplete message waiting for this fragment? */ | 2357 | if (*head || skb_unclone(frag, GFP_ATOMIC)) |
2481 | while (pbuf && ((buf_seqno(pbuf) != long_msg_seq_no) || | 2358 | goto out_free; |
2482 | (msg_orignode(fragm) != msg_orignode(buf_msg(pbuf))))) { | 2359 | *head = frag; |
2483 | prev = pbuf; | 2360 | skb_frag_list_init(*head); |
2484 | pbuf = pbuf->next; | ||
2485 | } | ||
2486 | |||
2487 | if (!pbuf && (msg_type(fragm) == FIRST_FRAGMENT)) { | ||
2488 | struct tipc_msg *imsg = (struct tipc_msg *)msg_data(fragm); | ||
2489 | u32 msg_sz = msg_size(imsg); | ||
2490 | u32 fragm_sz = msg_data_sz(fragm); | ||
2491 | u32 exp_fragm_cnt; | ||
2492 | u32 max = TIPC_MAX_USER_MSG_SIZE + NAMED_H_SIZE; | ||
2493 | |||
2494 | if (msg_type(imsg) == TIPC_MCAST_MSG) | ||
2495 | max = TIPC_MAX_USER_MSG_SIZE + MCAST_H_SIZE; | ||
2496 | if (fragm_sz == 0 || msg_size(imsg) > max) { | ||
2497 | kfree_skb(fbuf); | ||
2498 | return 0; | ||
2499 | } | ||
2500 | exp_fragm_cnt = msg_sz / fragm_sz + !!(msg_sz % fragm_sz); | ||
2501 | pbuf = tipc_buf_acquire(msg_size(imsg)); | ||
2502 | if (pbuf != NULL) { | ||
2503 | pbuf->next = *pending; | ||
2504 | *pending = pbuf; | ||
2505 | skb_copy_to_linear_data(pbuf, imsg, | ||
2506 | msg_data_sz(fragm)); | ||
2507 | /* Prepare buffer for subsequent fragments. */ | ||
2508 | set_long_msg_seqno(pbuf, long_msg_seq_no); | ||
2509 | set_fragm_size(pbuf, fragm_sz); | ||
2510 | set_expected_frags(pbuf, exp_fragm_cnt - 1); | ||
2511 | } else { | ||
2512 | pr_debug("Link unable to reassemble fragmented message\n"); | ||
2513 | kfree_skb(fbuf); | ||
2514 | return -1; | ||
2515 | } | ||
2516 | kfree_skb(fbuf); | ||
2517 | return 0; | ||
2518 | } else if (pbuf && (msg_type(fragm) != FIRST_FRAGMENT)) { | ||
2519 | u32 dsz = msg_data_sz(fragm); | ||
2520 | u32 fsz = get_fragm_size(pbuf); | ||
2521 | u32 crs = ((msg_fragm_no(fragm) - 1) * fsz); | ||
2522 | u32 exp_frags = get_expected_frags(pbuf) - 1; | ||
2523 | skb_copy_to_linear_data_offset(pbuf, crs, | ||
2524 | msg_data(fragm), dsz); | ||
2525 | kfree_skb(fbuf); | ||
2526 | |||
2527 | /* Is message complete? */ | ||
2528 | if (exp_frags == 0) { | ||
2529 | if (prev) | ||
2530 | prev->next = pbuf->next; | ||
2531 | else | ||
2532 | *pending = pbuf->next; | ||
2533 | msg_reset_reroute_cnt(buf_msg(pbuf)); | ||
2534 | *fb = pbuf; | ||
2535 | *m = buf_msg(pbuf); | ||
2536 | return 1; | ||
2537 | } | ||
2538 | set_expected_frags(pbuf, exp_frags); | ||
2539 | return 0; | 2361 | return 0; |
2362 | } else if (*head && | ||
2363 | skb_try_coalesce(*head, frag, &headstolen, &delta)) { | ||
2364 | kfree_skb_partial(frag, headstolen); | ||
2365 | } else { | ||
2366 | if (!*head) | ||
2367 | goto out_free; | ||
2368 | if (!skb_has_frag_list(*head)) | ||
2369 | skb_shinfo(*head)->frag_list = frag; | ||
2370 | else | ||
2371 | (*tail)->next = frag; | ||
2372 | *tail = frag; | ||
2373 | (*head)->truesize += frag->truesize; | ||
2374 | } | ||
2375 | if (fragid == LAST_FRAGMENT) { | ||
2376 | *fbuf = *head; | ||
2377 | *tail = *head = NULL; | ||
2378 | return LINK_REASM_COMPLETE; | ||
2540 | } | 2379 | } |
2541 | kfree_skb(fbuf); | ||
2542 | return 0; | 2380 | return 0; |
2381 | out_free: | ||
2382 | pr_warn_ratelimited("Link unable to reassemble fragmented message\n"); | ||
2383 | kfree_skb(*fbuf); | ||
2384 | return LINK_REASM_ERROR; | ||
2543 | } | 2385 | } |
2544 | 2386 | ||
2545 | static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance) | 2387 | static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance) |
@@ -2585,25 +2427,21 @@ void tipc_link_set_queue_limits(struct tipc_link *l_ptr, u32 window) | |||
2585 | static struct tipc_link *link_find_link(const char *name, | 2427 | static struct tipc_link *link_find_link(const char *name, |
2586 | struct tipc_node **node) | 2428 | struct tipc_node **node) |
2587 | { | 2429 | { |
2588 | struct tipc_link_name link_name_parts; | ||
2589 | struct tipc_bearer *b_ptr; | ||
2590 | struct tipc_link *l_ptr; | 2430 | struct tipc_link *l_ptr; |
2431 | struct tipc_node *n_ptr; | ||
2432 | int i; | ||
2591 | 2433 | ||
2592 | if (!link_name_validate(name, &link_name_parts)) | 2434 | list_for_each_entry(n_ptr, &tipc_node_list, list) { |
2593 | return NULL; | 2435 | for (i = 0; i < MAX_BEARERS; i++) { |
2594 | 2436 | l_ptr = n_ptr->links[i]; | |
2595 | b_ptr = tipc_bearer_find_interface(link_name_parts.if_local); | 2437 | if (l_ptr && !strcmp(l_ptr->name, name)) |
2596 | if (!b_ptr) | 2438 | goto found; |
2597 | return NULL; | 2439 | } |
2598 | 2440 | } | |
2599 | *node = tipc_node_find(link_name_parts.addr_peer); | 2441 | l_ptr = NULL; |
2600 | if (!*node) | 2442 | n_ptr = NULL; |
2601 | return NULL; | 2443 | found: |
2602 | 2444 | *node = n_ptr; | |
2603 | l_ptr = (*node)->links[b_ptr->identity]; | ||
2604 | if (!l_ptr || strcmp(l_ptr->name, name)) | ||
2605 | return NULL; | ||
2606 | |||
2607 | return l_ptr; | 2445 | return l_ptr; |
2608 | } | 2446 | } |
2609 | 2447 | ||
@@ -2646,6 +2484,7 @@ static int link_cmd_set_value(const char *name, u32 new_value, u16 cmd) | |||
2646 | struct tipc_link *l_ptr; | 2484 | struct tipc_link *l_ptr; |
2647 | struct tipc_bearer *b_ptr; | 2485 | struct tipc_bearer *b_ptr; |
2648 | struct tipc_media *m_ptr; | 2486 | struct tipc_media *m_ptr; |
2487 | int res = 0; | ||
2649 | 2488 | ||
2650 | l_ptr = link_find_link(name, &node); | 2489 | l_ptr = link_find_link(name, &node); |
2651 | if (l_ptr) { | 2490 | if (l_ptr) { |
@@ -2668,9 +2507,12 @@ static int link_cmd_set_value(const char *name, u32 new_value, u16 cmd) | |||
2668 | case TIPC_CMD_SET_LINK_WINDOW: | 2507 | case TIPC_CMD_SET_LINK_WINDOW: |
2669 | tipc_link_set_queue_limits(l_ptr, new_value); | 2508 | tipc_link_set_queue_limits(l_ptr, new_value); |
2670 | break; | 2509 | break; |
2510 | default: | ||
2511 | res = -EINVAL; | ||
2512 | break; | ||
2671 | } | 2513 | } |
2672 | tipc_node_unlock(node); | 2514 | tipc_node_unlock(node); |
2673 | return 0; | 2515 | return res; |
2674 | } | 2516 | } |
2675 | 2517 | ||
2676 | b_ptr = tipc_bearer_find(name); | 2518 | b_ptr = tipc_bearer_find(name); |
@@ -2678,15 +2520,18 @@ static int link_cmd_set_value(const char *name, u32 new_value, u16 cmd) | |||
2678 | switch (cmd) { | 2520 | switch (cmd) { |
2679 | case TIPC_CMD_SET_LINK_TOL: | 2521 | case TIPC_CMD_SET_LINK_TOL: |
2680 | b_ptr->tolerance = new_value; | 2522 | b_ptr->tolerance = new_value; |
2681 | return 0; | 2523 | break; |
2682 | case TIPC_CMD_SET_LINK_PRI: | 2524 | case TIPC_CMD_SET_LINK_PRI: |
2683 | b_ptr->priority = new_value; | 2525 | b_ptr->priority = new_value; |
2684 | return 0; | 2526 | break; |
2685 | case TIPC_CMD_SET_LINK_WINDOW: | 2527 | case TIPC_CMD_SET_LINK_WINDOW: |
2686 | b_ptr->window = new_value; | 2528 | b_ptr->window = new_value; |
2687 | return 0; | 2529 | break; |
2530 | default: | ||
2531 | res = -EINVAL; | ||
2532 | break; | ||
2688 | } | 2533 | } |
2689 | return -EINVAL; | 2534 | return res; |
2690 | } | 2535 | } |
2691 | 2536 | ||
2692 | m_ptr = tipc_media_find(name); | 2537 | m_ptr = tipc_media_find(name); |
@@ -2695,15 +2540,18 @@ static int link_cmd_set_value(const char *name, u32 new_value, u16 cmd) | |||
2695 | switch (cmd) { | 2540 | switch (cmd) { |
2696 | case TIPC_CMD_SET_LINK_TOL: | 2541 | case TIPC_CMD_SET_LINK_TOL: |
2697 | m_ptr->tolerance = new_value; | 2542 | m_ptr->tolerance = new_value; |
2698 | return 0; | 2543 | break; |
2699 | case TIPC_CMD_SET_LINK_PRI: | 2544 | case TIPC_CMD_SET_LINK_PRI: |
2700 | m_ptr->priority = new_value; | 2545 | m_ptr->priority = new_value; |
2701 | return 0; | 2546 | break; |
2702 | case TIPC_CMD_SET_LINK_WINDOW: | 2547 | case TIPC_CMD_SET_LINK_WINDOW: |
2703 | m_ptr->window = new_value; | 2548 | m_ptr->window = new_value; |
2704 | return 0; | 2549 | break; |
2550 | default: | ||
2551 | res = -EINVAL; | ||
2552 | break; | ||
2705 | } | 2553 | } |
2706 | return -EINVAL; | 2554 | return res; |
2707 | } | 2555 | } |
2708 | 2556 | ||
2709 | struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space, | 2557 | struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space, |
diff --git a/net/tipc/link.h b/net/tipc/link.h index c048ed1cbd76..8a6c1026644d 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h | |||
@@ -41,6 +41,12 @@ | |||
41 | #include "node.h" | 41 | #include "node.h" |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * Link reassembly status codes | ||
45 | */ | ||
46 | #define LINK_REASM_ERROR -1 | ||
47 | #define LINK_REASM_COMPLETE 1 | ||
48 | |||
49 | /* | ||
44 | * Out-of-range value for link sequence numbers | 50 | * Out-of-range value for link sequence numbers |
45 | */ | 51 | */ |
46 | #define INVALID_LINK_SEQ 0x10000 | 52 | #define INVALID_LINK_SEQ 0x10000 |
@@ -134,7 +140,8 @@ struct tipc_stats { | |||
134 | * @next_out: ptr to first unsent outbound message in queue | 140 | * @next_out: ptr to first unsent outbound message in queue |
135 | * @waiting_ports: linked list of ports waiting for link congestion to abate | 141 | * @waiting_ports: linked list of ports waiting for link congestion to abate |
136 | * @long_msg_seq_no: next identifier to use for outbound fragmented messages | 142 | * @long_msg_seq_no: next identifier to use for outbound fragmented messages |
137 | * @defragm_buf: list of partially reassembled inbound message fragments | 143 | * @reasm_head: list head of partially reassembled inbound message fragments |
144 | * @reasm_tail: last fragment received | ||
138 | * @stats: collects statistics regarding link activity | 145 | * @stats: collects statistics regarding link activity |
139 | */ | 146 | */ |
140 | struct tipc_link { | 147 | struct tipc_link { |
@@ -196,9 +203,10 @@ struct tipc_link { | |||
196 | struct sk_buff *next_out; | 203 | struct sk_buff *next_out; |
197 | struct list_head waiting_ports; | 204 | struct list_head waiting_ports; |
198 | 205 | ||
199 | /* Fragmentation/defragmentation */ | 206 | /* Fragmentation/reassembly */ |
200 | u32 long_msg_seq_no; | 207 | u32 long_msg_seq_no; |
201 | struct sk_buff *defragm_buf; | 208 | struct sk_buff *reasm_head; |
209 | struct sk_buff *reasm_tail; | ||
202 | 210 | ||
203 | /* Statistics */ | 211 | /* Statistics */ |
204 | struct tipc_stats stats; | 212 | struct tipc_stats stats; |
@@ -227,13 +235,11 @@ int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf); | |||
227 | u32 tipc_link_get_max_pkt(u32 dest, u32 selector); | 235 | u32 tipc_link_get_max_pkt(u32 dest, u32 selector); |
228 | int tipc_link_send_sections_fast(struct tipc_port *sender, | 236 | int tipc_link_send_sections_fast(struct tipc_port *sender, |
229 | struct iovec const *msg_sect, | 237 | struct iovec const *msg_sect, |
230 | const u32 num_sect, | 238 | unsigned int len, u32 destnode); |
231 | unsigned int total_len, | ||
232 | u32 destnode); | ||
233 | void tipc_link_recv_bundle(struct sk_buff *buf); | 239 | void tipc_link_recv_bundle(struct sk_buff *buf); |
234 | int tipc_link_recv_fragment(struct sk_buff **pending, | 240 | int tipc_link_recv_fragment(struct sk_buff **reasm_head, |
235 | struct sk_buff **fb, | 241 | struct sk_buff **reasm_tail, |
236 | struct tipc_msg **msg); | 242 | struct sk_buff **fbuf); |
237 | void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ, int prob, | 243 | void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ, int prob, |
238 | u32 gap, u32 tolerance, u32 priority, | 244 | u32 gap, u32 tolerance, u32 priority, |
239 | u32 acked_mtu); | 245 | u32 acked_mtu); |
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index ced60e2fc4f7..e525f8ce1dee 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c | |||
@@ -73,13 +73,13 @@ void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, | |||
73 | * Returns message data size or errno | 73 | * Returns message data size or errno |
74 | */ | 74 | */ |
75 | int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, | 75 | int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, |
76 | u32 num_sect, unsigned int total_len, int max_size, | 76 | unsigned int len, int max_size, struct sk_buff **buf) |
77 | struct sk_buff **buf) | ||
78 | { | 77 | { |
79 | int dsz, sz, hsz, pos, res, cnt; | 78 | int dsz, sz, hsz; |
79 | unsigned char *to; | ||
80 | 80 | ||
81 | dsz = total_len; | 81 | dsz = len; |
82 | pos = hsz = msg_hdr_sz(hdr); | 82 | hsz = msg_hdr_sz(hdr); |
83 | sz = hsz + dsz; | 83 | sz = hsz + dsz; |
84 | msg_set_size(hdr, sz); | 84 | msg_set_size(hdr, sz); |
85 | if (unlikely(sz > max_size)) { | 85 | if (unlikely(sz > max_size)) { |
@@ -91,16 +91,11 @@ int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, | |||
91 | if (!(*buf)) | 91 | if (!(*buf)) |
92 | return -ENOMEM; | 92 | return -ENOMEM; |
93 | skb_copy_to_linear_data(*buf, hdr, hsz); | 93 | skb_copy_to_linear_data(*buf, hdr, hsz); |
94 | for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) { | 94 | to = (*buf)->data + hsz; |
95 | skb_copy_to_linear_data_offset(*buf, pos, | 95 | if (len && memcpy_fromiovecend(to, msg_sect, 0, dsz)) { |
96 | msg_sect[cnt].iov_base, | 96 | kfree_skb(*buf); |
97 | msg_sect[cnt].iov_len); | 97 | *buf = NULL; |
98 | pos += msg_sect[cnt].iov_len; | 98 | return -EFAULT; |
99 | } | 99 | } |
100 | if (likely(res)) | 100 | return dsz; |
101 | return dsz; | ||
102 | |||
103 | kfree_skb(*buf); | ||
104 | *buf = NULL; | ||
105 | return -EFAULT; | ||
106 | } | 101 | } |
diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 5e4ccf5c27df..76d1269b9443 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h | |||
@@ -554,12 +554,6 @@ static inline void msg_set_last_bcast(struct tipc_msg *m, u32 n) | |||
554 | msg_set_bits(m, 4, 16, 0xffff, n); | 554 | msg_set_bits(m, 4, 16, 0xffff, n); |
555 | } | 555 | } |
556 | 556 | ||
557 | |||
558 | static inline u32 msg_fragm_no(struct tipc_msg *m) | ||
559 | { | ||
560 | return msg_bits(m, 4, 16, 0xffff); | ||
561 | } | ||
562 | |||
563 | static inline void msg_set_fragm_no(struct tipc_msg *m, u32 n) | 557 | static inline void msg_set_fragm_no(struct tipc_msg *m, u32 n) |
564 | { | 558 | { |
565 | msg_set_bits(m, 4, 16, 0xffff, n); | 559 | msg_set_bits(m, 4, 16, 0xffff, n); |
@@ -576,12 +570,6 @@ static inline void msg_set_next_sent(struct tipc_msg *m, u32 n) | |||
576 | msg_set_bits(m, 4, 0, 0xffff, n); | 570 | msg_set_bits(m, 4, 0, 0xffff, n); |
577 | } | 571 | } |
578 | 572 | ||
579 | |||
580 | static inline u32 msg_long_msgno(struct tipc_msg *m) | ||
581 | { | ||
582 | return msg_bits(m, 4, 0, 0xffff); | ||
583 | } | ||
584 | |||
585 | static inline void msg_set_long_msgno(struct tipc_msg *m, u32 n) | 573 | static inline void msg_set_long_msgno(struct tipc_msg *m, u32 n) |
586 | { | 574 | { |
587 | msg_set_bits(m, 4, 0, 0xffff, n); | 575 | msg_set_bits(m, 4, 0, 0xffff, n); |
@@ -722,6 +710,5 @@ u32 tipc_msg_tot_importance(struct tipc_msg *m); | |||
722 | void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, | 710 | void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, |
723 | u32 destnode); | 711 | u32 destnode); |
724 | int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, | 712 | int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, |
725 | u32 num_sect, unsigned int total_len, int max_size, | 713 | unsigned int len, int max_size, struct sk_buff **buf); |
726 | struct sk_buff **buf); | ||
727 | #endif | 714 | #endif |
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 8bcd4985d0fb..9f72a6376362 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c | |||
@@ -76,9 +76,11 @@ static struct genl_family tipc_genl_family = { | |||
76 | .maxattr = 0, | 76 | .maxattr = 0, |
77 | }; | 77 | }; |
78 | 78 | ||
79 | static struct genl_ops tipc_genl_ops = { | 79 | static struct genl_ops tipc_genl_ops[] = { |
80 | .cmd = TIPC_GENL_CMD, | 80 | { |
81 | .doit = handle_cmd, | 81 | .cmd = TIPC_GENL_CMD, |
82 | .doit = handle_cmd, | ||
83 | }, | ||
82 | }; | 84 | }; |
83 | 85 | ||
84 | static int tipc_genl_family_registered; | 86 | static int tipc_genl_family_registered; |
@@ -87,8 +89,7 @@ int tipc_netlink_start(void) | |||
87 | { | 89 | { |
88 | int res; | 90 | int res; |
89 | 91 | ||
90 | res = genl_register_family_with_ops(&tipc_genl_family, | 92 | res = genl_register_family_with_ops(&tipc_genl_family, tipc_genl_ops); |
91 | &tipc_genl_ops, 1); | ||
92 | if (res) { | 93 | if (res) { |
93 | pr_err("Failed to register netlink interface\n"); | 94 | pr_err("Failed to register netlink interface\n"); |
94 | return res; | 95 | return res; |
diff --git a/net/tipc/node.c b/net/tipc/node.c index 6e6c434872e8..25100c0a6fe8 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -298,9 +298,10 @@ static void node_lost_contact(struct tipc_node *n_ptr) | |||
298 | } | 298 | } |
299 | n_ptr->bclink.deferred_size = 0; | 299 | n_ptr->bclink.deferred_size = 0; |
300 | 300 | ||
301 | if (n_ptr->bclink.defragm) { | 301 | if (n_ptr->bclink.reasm_head) { |
302 | kfree_skb(n_ptr->bclink.defragm); | 302 | kfree_skb(n_ptr->bclink.reasm_head); |
303 | n_ptr->bclink.defragm = NULL; | 303 | n_ptr->bclink.reasm_head = NULL; |
304 | n_ptr->bclink.reasm_tail = NULL; | ||
304 | } | 305 | } |
305 | 306 | ||
306 | tipc_bclink_remove_node(n_ptr->addr); | 307 | tipc_bclink_remove_node(n_ptr->addr); |
diff --git a/net/tipc/node.h b/net/tipc/node.h index 3c189b35b102..e5e96c04e167 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h | |||
@@ -74,7 +74,8 @@ | |||
74 | * @deferred_size: number of OOS b'cast messages in deferred queue | 74 | * @deferred_size: number of OOS b'cast messages in deferred queue |
75 | * @deferred_head: oldest OOS b'cast message received from node | 75 | * @deferred_head: oldest OOS b'cast message received from node |
76 | * @deferred_tail: newest OOS b'cast message received from node | 76 | * @deferred_tail: newest OOS b'cast message received from node |
77 | * @defragm: list of partially reassembled b'cast message fragments from node | 77 | * @reasm_head: broadcast reassembly queue head from node |
78 | * @reasm_tail: last broadcast fragment received from node | ||
78 | * @recv_permitted: true if node is allowed to receive b'cast messages | 79 | * @recv_permitted: true if node is allowed to receive b'cast messages |
79 | */ | 80 | */ |
80 | struct tipc_node { | 81 | struct tipc_node { |
@@ -98,7 +99,8 @@ struct tipc_node { | |||
98 | u32 deferred_size; | 99 | u32 deferred_size; |
99 | struct sk_buff *deferred_head; | 100 | struct sk_buff *deferred_head; |
100 | struct sk_buff *deferred_tail; | 101 | struct sk_buff *deferred_tail; |
101 | struct sk_buff *defragm; | 102 | struct sk_buff *reasm_head; |
103 | struct sk_buff *reasm_tail; | ||
102 | bool recv_permitted; | 104 | bool recv_permitted; |
103 | } bclink; | 105 | } bclink; |
104 | }; | 106 | }; |
diff --git a/net/tipc/port.c b/net/tipc/port.c index b3ed2fcab4fb..d43f3182b1d4 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c | |||
@@ -90,8 +90,7 @@ int tipc_port_peer_msg(struct tipc_port *p_ptr, struct tipc_msg *msg) | |||
90 | * tipc_multicast - send a multicast message to local and remote destinations | 90 | * tipc_multicast - send a multicast message to local and remote destinations |
91 | */ | 91 | */ |
92 | int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, | 92 | int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, |
93 | u32 num_sect, struct iovec const *msg_sect, | 93 | struct iovec const *msg_sect, unsigned int len) |
94 | unsigned int total_len) | ||
95 | { | 94 | { |
96 | struct tipc_msg *hdr; | 95 | struct tipc_msg *hdr; |
97 | struct sk_buff *buf; | 96 | struct sk_buff *buf; |
@@ -114,8 +113,7 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, | |||
114 | msg_set_namelower(hdr, seq->lower); | 113 | msg_set_namelower(hdr, seq->lower); |
115 | msg_set_nameupper(hdr, seq->upper); | 114 | msg_set_nameupper(hdr, seq->upper); |
116 | msg_set_hdr_sz(hdr, MCAST_H_SIZE); | 115 | msg_set_hdr_sz(hdr, MCAST_H_SIZE); |
117 | res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, MAX_MSG_SIZE, | 116 | res = tipc_msg_build(hdr, msg_sect, len, MAX_MSG_SIZE, &buf); |
118 | &buf); | ||
119 | if (unlikely(!buf)) | 117 | if (unlikely(!buf)) |
120 | return res; | 118 | return res; |
121 | 119 | ||
@@ -253,18 +251,15 @@ struct tipc_port *tipc_createport(struct sock *sk, | |||
253 | return p_ptr; | 251 | return p_ptr; |
254 | } | 252 | } |
255 | 253 | ||
256 | int tipc_deleteport(u32 ref) | 254 | int tipc_deleteport(struct tipc_port *p_ptr) |
257 | { | 255 | { |
258 | struct tipc_port *p_ptr; | ||
259 | struct sk_buff *buf = NULL; | 256 | struct sk_buff *buf = NULL; |
260 | 257 | ||
261 | tipc_withdraw(ref, 0, NULL); | 258 | tipc_withdraw(p_ptr, 0, NULL); |
262 | p_ptr = tipc_port_lock(ref); | ||
263 | if (!p_ptr) | ||
264 | return -EINVAL; | ||
265 | 259 | ||
266 | tipc_ref_discard(ref); | 260 | spin_lock_bh(p_ptr->lock); |
267 | tipc_port_unlock(p_ptr); | 261 | tipc_ref_discard(p_ptr->ref); |
262 | spin_unlock_bh(p_ptr->lock); | ||
268 | 263 | ||
269 | k_cancel_timer(&p_ptr->timer); | 264 | k_cancel_timer(&p_ptr->timer); |
270 | if (p_ptr->connected) { | 265 | if (p_ptr->connected) { |
@@ -436,14 +431,13 @@ exit: | |||
436 | } | 431 | } |
437 | 432 | ||
438 | int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr, | 433 | int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr, |
439 | struct iovec const *msg_sect, u32 num_sect, | 434 | struct iovec const *msg_sect, unsigned int len, |
440 | unsigned int total_len, int err) | 435 | int err) |
441 | { | 436 | { |
442 | struct sk_buff *buf; | 437 | struct sk_buff *buf; |
443 | int res; | 438 | int res; |
444 | 439 | ||
445 | res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, MAX_MSG_SIZE, | 440 | res = tipc_msg_build(hdr, msg_sect, len, MAX_MSG_SIZE, &buf); |
446 | &buf); | ||
447 | if (!buf) | 441 | if (!buf) |
448 | return res; | 442 | return res; |
449 | 443 | ||
@@ -707,47 +701,36 @@ int tipc_set_portimportance(u32 ref, unsigned int imp) | |||
707 | } | 701 | } |
708 | 702 | ||
709 | 703 | ||
710 | int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) | 704 | int tipc_publish(struct tipc_port *p_ptr, unsigned int scope, |
705 | struct tipc_name_seq const *seq) | ||
711 | { | 706 | { |
712 | struct tipc_port *p_ptr; | ||
713 | struct publication *publ; | 707 | struct publication *publ; |
714 | u32 key; | 708 | u32 key; |
715 | int res = -EINVAL; | ||
716 | 709 | ||
717 | p_ptr = tipc_port_lock(ref); | 710 | if (p_ptr->connected) |
718 | if (!p_ptr) | ||
719 | return -EINVAL; | 711 | return -EINVAL; |
712 | key = p_ptr->ref + p_ptr->pub_count + 1; | ||
713 | if (key == p_ptr->ref) | ||
714 | return -EADDRINUSE; | ||
720 | 715 | ||
721 | if (p_ptr->connected) | ||
722 | goto exit; | ||
723 | key = ref + p_ptr->pub_count + 1; | ||
724 | if (key == ref) { | ||
725 | res = -EADDRINUSE; | ||
726 | goto exit; | ||
727 | } | ||
728 | publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper, | 716 | publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper, |
729 | scope, p_ptr->ref, key); | 717 | scope, p_ptr->ref, key); |
730 | if (publ) { | 718 | if (publ) { |
731 | list_add(&publ->pport_list, &p_ptr->publications); | 719 | list_add(&publ->pport_list, &p_ptr->publications); |
732 | p_ptr->pub_count++; | 720 | p_ptr->pub_count++; |
733 | p_ptr->published = 1; | 721 | p_ptr->published = 1; |
734 | res = 0; | 722 | return 0; |
735 | } | 723 | } |
736 | exit: | 724 | return -EINVAL; |
737 | tipc_port_unlock(p_ptr); | ||
738 | return res; | ||
739 | } | 725 | } |
740 | 726 | ||
741 | int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) | 727 | int tipc_withdraw(struct tipc_port *p_ptr, unsigned int scope, |
728 | struct tipc_name_seq const *seq) | ||
742 | { | 729 | { |
743 | struct tipc_port *p_ptr; | ||
744 | struct publication *publ; | 730 | struct publication *publ; |
745 | struct publication *tpubl; | 731 | struct publication *tpubl; |
746 | int res = -EINVAL; | 732 | int res = -EINVAL; |
747 | 733 | ||
748 | p_ptr = tipc_port_lock(ref); | ||
749 | if (!p_ptr) | ||
750 | return -EINVAL; | ||
751 | if (!seq) { | 734 | if (!seq) { |
752 | list_for_each_entry_safe(publ, tpubl, | 735 | list_for_each_entry_safe(publ, tpubl, |
753 | &p_ptr->publications, pport_list) { | 736 | &p_ptr->publications, pport_list) { |
@@ -774,7 +757,6 @@ int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) | |||
774 | } | 757 | } |
775 | if (list_empty(&p_ptr->publications)) | 758 | if (list_empty(&p_ptr->publications)) |
776 | p_ptr->published = 0; | 759 | p_ptr->published = 0; |
777 | tipc_port_unlock(p_ptr); | ||
778 | return res; | 760 | return res; |
779 | } | 761 | } |
780 | 762 | ||
@@ -918,15 +900,14 @@ int tipc_port_recv_msg(struct sk_buff *buf) | |||
918 | * tipc_port_recv_sections(): Concatenate and deliver sectioned | 900 | * tipc_port_recv_sections(): Concatenate and deliver sectioned |
919 | * message for this node. | 901 | * message for this node. |
920 | */ | 902 | */ |
921 | static int tipc_port_recv_sections(struct tipc_port *sender, unsigned int num_sect, | 903 | static int tipc_port_recv_sections(struct tipc_port *sender, |
922 | struct iovec const *msg_sect, | 904 | struct iovec const *msg_sect, |
923 | unsigned int total_len) | 905 | unsigned int len) |
924 | { | 906 | { |
925 | struct sk_buff *buf; | 907 | struct sk_buff *buf; |
926 | int res; | 908 | int res; |
927 | 909 | ||
928 | res = tipc_msg_build(&sender->phdr, msg_sect, num_sect, total_len, | 910 | res = tipc_msg_build(&sender->phdr, msg_sect, len, MAX_MSG_SIZE, &buf); |
929 | MAX_MSG_SIZE, &buf); | ||
930 | if (likely(buf)) | 911 | if (likely(buf)) |
931 | tipc_port_recv_msg(buf); | 912 | tipc_port_recv_msg(buf); |
932 | return res; | 913 | return res; |
@@ -935,8 +916,7 @@ static int tipc_port_recv_sections(struct tipc_port *sender, unsigned int num_se | |||
935 | /** | 916 | /** |
936 | * tipc_send - send message sections on connection | 917 | * tipc_send - send message sections on connection |
937 | */ | 918 | */ |
938 | int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect, | 919 | int tipc_send(u32 ref, struct iovec const *msg_sect, unsigned int len) |
939 | unsigned int total_len) | ||
940 | { | 920 | { |
941 | struct tipc_port *p_ptr; | 921 | struct tipc_port *p_ptr; |
942 | u32 destnode; | 922 | u32 destnode; |
@@ -950,11 +930,10 @@ int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect, | |||
950 | if (!tipc_port_congested(p_ptr)) { | 930 | if (!tipc_port_congested(p_ptr)) { |
951 | destnode = port_peernode(p_ptr); | 931 | destnode = port_peernode(p_ptr); |
952 | if (likely(!in_own_node(destnode))) | 932 | if (likely(!in_own_node(destnode))) |
953 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, | 933 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, |
954 | total_len, destnode); | 934 | len, destnode); |
955 | else | 935 | else |
956 | res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect, | 936 | res = tipc_port_recv_sections(p_ptr, msg_sect, len); |
957 | total_len); | ||
958 | 937 | ||
959 | if (likely(res != -ELINKCONG)) { | 938 | if (likely(res != -ELINKCONG)) { |
960 | p_ptr->congested = 0; | 939 | p_ptr->congested = 0; |
@@ -965,7 +944,7 @@ int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect, | |||
965 | } | 944 | } |
966 | if (port_unreliable(p_ptr)) { | 945 | if (port_unreliable(p_ptr)) { |
967 | p_ptr->congested = 0; | 946 | p_ptr->congested = 0; |
968 | return total_len; | 947 | return len; |
969 | } | 948 | } |
970 | return -ELINKCONG; | 949 | return -ELINKCONG; |
971 | } | 950 | } |
@@ -974,8 +953,7 @@ int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect, | |||
974 | * tipc_send2name - send message sections to port name | 953 | * tipc_send2name - send message sections to port name |
975 | */ | 954 | */ |
976 | int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, | 955 | int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, |
977 | unsigned int num_sect, struct iovec const *msg_sect, | 956 | struct iovec const *msg_sect, unsigned int len) |
978 | unsigned int total_len) | ||
979 | { | 957 | { |
980 | struct tipc_port *p_ptr; | 958 | struct tipc_port *p_ptr; |
981 | struct tipc_msg *msg; | 959 | struct tipc_msg *msg; |
@@ -999,36 +977,32 @@ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, | |||
999 | 977 | ||
1000 | if (likely(destport || destnode)) { | 978 | if (likely(destport || destnode)) { |
1001 | if (likely(in_own_node(destnode))) | 979 | if (likely(in_own_node(destnode))) |
1002 | res = tipc_port_recv_sections(p_ptr, num_sect, | 980 | res = tipc_port_recv_sections(p_ptr, msg_sect, len); |
1003 | msg_sect, total_len); | ||
1004 | else if (tipc_own_addr) | 981 | else if (tipc_own_addr) |
1005 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, | 982 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, |
1006 | num_sect, total_len, | 983 | len, destnode); |
1007 | destnode); | ||
1008 | else | 984 | else |
1009 | res = tipc_port_reject_sections(p_ptr, msg, msg_sect, | 985 | res = tipc_port_reject_sections(p_ptr, msg, msg_sect, |
1010 | num_sect, total_len, | 986 | len, TIPC_ERR_NO_NODE); |
1011 | TIPC_ERR_NO_NODE); | ||
1012 | if (likely(res != -ELINKCONG)) { | 987 | if (likely(res != -ELINKCONG)) { |
1013 | if (res > 0) | 988 | if (res > 0) |
1014 | p_ptr->sent++; | 989 | p_ptr->sent++; |
1015 | return res; | 990 | return res; |
1016 | } | 991 | } |
1017 | if (port_unreliable(p_ptr)) { | 992 | if (port_unreliable(p_ptr)) { |
1018 | return total_len; | 993 | return len; |
1019 | } | 994 | } |
1020 | return -ELINKCONG; | 995 | return -ELINKCONG; |
1021 | } | 996 | } |
1022 | return tipc_port_reject_sections(p_ptr, msg, msg_sect, num_sect, | 997 | return tipc_port_reject_sections(p_ptr, msg, msg_sect, len, |
1023 | total_len, TIPC_ERR_NO_NAME); | 998 | TIPC_ERR_NO_NAME); |
1024 | } | 999 | } |
1025 | 1000 | ||
1026 | /** | 1001 | /** |
1027 | * tipc_send2port - send message sections to port identity | 1002 | * tipc_send2port - send message sections to port identity |
1028 | */ | 1003 | */ |
1029 | int tipc_send2port(u32 ref, struct tipc_portid const *dest, | 1004 | int tipc_send2port(u32 ref, struct tipc_portid const *dest, |
1030 | unsigned int num_sect, struct iovec const *msg_sect, | 1005 | struct iovec const *msg_sect, unsigned int len) |
1031 | unsigned int total_len) | ||
1032 | { | 1006 | { |
1033 | struct tipc_port *p_ptr; | 1007 | struct tipc_port *p_ptr; |
1034 | struct tipc_msg *msg; | 1008 | struct tipc_msg *msg; |
@@ -1046,21 +1020,20 @@ int tipc_send2port(u32 ref, struct tipc_portid const *dest, | |||
1046 | msg_set_hdr_sz(msg, BASIC_H_SIZE); | 1020 | msg_set_hdr_sz(msg, BASIC_H_SIZE); |
1047 | 1021 | ||
1048 | if (in_own_node(dest->node)) | 1022 | if (in_own_node(dest->node)) |
1049 | res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect, | 1023 | res = tipc_port_recv_sections(p_ptr, msg_sect, len); |
1050 | total_len); | ||
1051 | else if (tipc_own_addr) | 1024 | else if (tipc_own_addr) |
1052 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, | 1025 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, len, |
1053 | total_len, dest->node); | 1026 | dest->node); |
1054 | else | 1027 | else |
1055 | res = tipc_port_reject_sections(p_ptr, msg, msg_sect, num_sect, | 1028 | res = tipc_port_reject_sections(p_ptr, msg, msg_sect, len, |
1056 | total_len, TIPC_ERR_NO_NODE); | 1029 | TIPC_ERR_NO_NODE); |
1057 | if (likely(res != -ELINKCONG)) { | 1030 | if (likely(res != -ELINKCONG)) { |
1058 | if (res > 0) | 1031 | if (res > 0) |
1059 | p_ptr->sent++; | 1032 | p_ptr->sent++; |
1060 | return res; | 1033 | return res; |
1061 | } | 1034 | } |
1062 | if (port_unreliable(p_ptr)) { | 1035 | if (port_unreliable(p_ptr)) { |
1063 | return total_len; | 1036 | return len; |
1064 | } | 1037 | } |
1065 | return -ELINKCONG; | 1038 | return -ELINKCONG; |
1066 | } | 1039 | } |
diff --git a/net/tipc/port.h b/net/tipc/port.h index 5a7026b9c345..34f12bd4074e 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h | |||
@@ -116,7 +116,7 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err); | |||
116 | 116 | ||
117 | void tipc_acknowledge(u32 port_ref, u32 ack); | 117 | void tipc_acknowledge(u32 port_ref, u32 ack); |
118 | 118 | ||
119 | int tipc_deleteport(u32 portref); | 119 | int tipc_deleteport(struct tipc_port *p_ptr); |
120 | 120 | ||
121 | int tipc_portimportance(u32 portref, unsigned int *importance); | 121 | int tipc_portimportance(u32 portref, unsigned int *importance); |
122 | int tipc_set_portimportance(u32 portref, unsigned int importance); | 122 | int tipc_set_portimportance(u32 portref, unsigned int importance); |
@@ -127,9 +127,9 @@ int tipc_set_portunreliable(u32 portref, unsigned int isunreliable); | |||
127 | int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable); | 127 | int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable); |
128 | int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable); | 128 | int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable); |
129 | 129 | ||
130 | int tipc_publish(u32 portref, unsigned int scope, | 130 | int tipc_publish(struct tipc_port *p_ptr, unsigned int scope, |
131 | struct tipc_name_seq const *name_seq); | 131 | struct tipc_name_seq const *name_seq); |
132 | int tipc_withdraw(u32 portref, unsigned int scope, | 132 | int tipc_withdraw(struct tipc_port *p_ptr, unsigned int scope, |
133 | struct tipc_name_seq const *name_seq); | 133 | struct tipc_name_seq const *name_seq); |
134 | 134 | ||
135 | int tipc_connect(u32 portref, struct tipc_portid const *port); | 135 | int tipc_connect(u32 portref, struct tipc_portid const *port); |
@@ -151,24 +151,20 @@ int tipc_port_peer_msg(struct tipc_port *p_ptr, struct tipc_msg *msg); | |||
151 | * TIPC messaging routines | 151 | * TIPC messaging routines |
152 | */ | 152 | */ |
153 | int tipc_port_recv_msg(struct sk_buff *buf); | 153 | int tipc_port_recv_msg(struct sk_buff *buf); |
154 | int tipc_send(u32 portref, unsigned int num_sect, struct iovec const *msg_sect, | 154 | int tipc_send(u32 portref, struct iovec const *msg_sect, unsigned int len); |
155 | unsigned int total_len); | ||
156 | 155 | ||
157 | int tipc_send2name(u32 portref, struct tipc_name const *name, u32 domain, | 156 | int tipc_send2name(u32 portref, struct tipc_name const *name, u32 domain, |
158 | unsigned int num_sect, struct iovec const *msg_sect, | 157 | struct iovec const *msg_sect, unsigned int len); |
159 | unsigned int total_len); | ||
160 | 158 | ||
161 | int tipc_send2port(u32 portref, struct tipc_portid const *dest, | 159 | int tipc_send2port(u32 portref, struct tipc_portid const *dest, |
162 | unsigned int num_sect, struct iovec const *msg_sect, | 160 | struct iovec const *msg_sect, unsigned int len); |
163 | unsigned int total_len); | ||
164 | 161 | ||
165 | int tipc_multicast(u32 portref, struct tipc_name_seq const *seq, | 162 | int tipc_multicast(u32 portref, struct tipc_name_seq const *seq, |
166 | unsigned int section_count, struct iovec const *msg, | 163 | struct iovec const *msg, unsigned int len); |
167 | unsigned int total_len); | ||
168 | 164 | ||
169 | int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr, | 165 | int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr, |
170 | struct iovec const *msg_sect, u32 num_sect, | 166 | struct iovec const *msg_sect, unsigned int len, |
171 | unsigned int total_len, int err); | 167 | int err); |
172 | struct sk_buff *tipc_port_get_ports(void); | 168 | struct sk_buff *tipc_port_get_ports(void); |
173 | void tipc_port_recv_proto_msg(struct sk_buff *buf); | 169 | void tipc_port_recv_proto_msg(struct sk_buff *buf); |
174 | void tipc_port_recv_mcast(struct sk_buff *buf, struct tipc_port_list *dp); | 170 | void tipc_port_recv_mcast(struct sk_buff *buf, struct tipc_port_list *dp); |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 6cc7ddd2fb7c..e741416d1d24 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -338,7 +338,7 @@ static int release(struct socket *sock) | |||
338 | buf = __skb_dequeue(&sk->sk_receive_queue); | 338 | buf = __skb_dequeue(&sk->sk_receive_queue); |
339 | if (buf == NULL) | 339 | if (buf == NULL) |
340 | break; | 340 | break; |
341 | if (TIPC_SKB_CB(buf)->handle != 0) | 341 | if (TIPC_SKB_CB(buf)->handle != NULL) |
342 | kfree_skb(buf); | 342 | kfree_skb(buf); |
343 | else { | 343 | else { |
344 | if ((sock->state == SS_CONNECTING) || | 344 | if ((sock->state == SS_CONNECTING) || |
@@ -354,7 +354,7 @@ static int release(struct socket *sock) | |||
354 | * Delete TIPC port; this ensures no more messages are queued | 354 | * Delete TIPC port; this ensures no more messages are queued |
355 | * (also disconnects an active connection & sends a 'FIN-' to peer) | 355 | * (also disconnects an active connection & sends a 'FIN-' to peer) |
356 | */ | 356 | */ |
357 | res = tipc_deleteport(tport->ref); | 357 | res = tipc_deleteport(tport); |
358 | 358 | ||
359 | /* Discard any remaining (connection-based) messages in receive queue */ | 359 | /* Discard any remaining (connection-based) messages in receive queue */ |
360 | __skb_queue_purge(&sk->sk_receive_queue); | 360 | __skb_queue_purge(&sk->sk_receive_queue); |
@@ -386,30 +386,46 @@ static int release(struct socket *sock) | |||
386 | */ | 386 | */ |
387 | static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) | 387 | static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) |
388 | { | 388 | { |
389 | struct sock *sk = sock->sk; | ||
389 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; | 390 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; |
390 | u32 portref = tipc_sk_port(sock->sk)->ref; | 391 | struct tipc_port *tport = tipc_sk_port(sock->sk); |
392 | int res = -EINVAL; | ||
391 | 393 | ||
392 | if (unlikely(!uaddr_len)) | 394 | lock_sock(sk); |
393 | return tipc_withdraw(portref, 0, NULL); | 395 | if (unlikely(!uaddr_len)) { |
396 | res = tipc_withdraw(tport, 0, NULL); | ||
397 | goto exit; | ||
398 | } | ||
394 | 399 | ||
395 | if (uaddr_len < sizeof(struct sockaddr_tipc)) | 400 | if (uaddr_len < sizeof(struct sockaddr_tipc)) { |
396 | return -EINVAL; | 401 | res = -EINVAL; |
397 | if (addr->family != AF_TIPC) | 402 | goto exit; |
398 | return -EAFNOSUPPORT; | 403 | } |
404 | if (addr->family != AF_TIPC) { | ||
405 | res = -EAFNOSUPPORT; | ||
406 | goto exit; | ||
407 | } | ||
399 | 408 | ||
400 | if (addr->addrtype == TIPC_ADDR_NAME) | 409 | if (addr->addrtype == TIPC_ADDR_NAME) |
401 | addr->addr.nameseq.upper = addr->addr.nameseq.lower; | 410 | addr->addr.nameseq.upper = addr->addr.nameseq.lower; |
402 | else if (addr->addrtype != TIPC_ADDR_NAMESEQ) | 411 | else if (addr->addrtype != TIPC_ADDR_NAMESEQ) { |
403 | return -EAFNOSUPPORT; | 412 | res = -EAFNOSUPPORT; |
413 | goto exit; | ||
414 | } | ||
404 | 415 | ||
405 | if ((addr->addr.nameseq.type < TIPC_RESERVED_TYPES) && | 416 | if ((addr->addr.nameseq.type < TIPC_RESERVED_TYPES) && |
406 | (addr->addr.nameseq.type != TIPC_TOP_SRV) && | 417 | (addr->addr.nameseq.type != TIPC_TOP_SRV) && |
407 | (addr->addr.nameseq.type != TIPC_CFG_SRV)) | 418 | (addr->addr.nameseq.type != TIPC_CFG_SRV)) { |
408 | return -EACCES; | 419 | res = -EACCES; |
420 | goto exit; | ||
421 | } | ||
409 | 422 | ||
410 | return (addr->scope > 0) ? | 423 | res = (addr->scope > 0) ? |
411 | tipc_publish(portref, addr->scope, &addr->addr.nameseq) : | 424 | tipc_publish(tport, addr->scope, &addr->addr.nameseq) : |
412 | tipc_withdraw(portref, -addr->scope, &addr->addr.nameseq); | 425 | tipc_withdraw(tport, -addr->scope, &addr->addr.nameseq); |
426 | exit: | ||
427 | release_sock(sk); | ||
428 | return res; | ||
413 | } | 429 | } |
414 | 430 | ||
415 | /** | 431 | /** |
@@ -622,13 +638,11 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
622 | res = tipc_send2name(tport->ref, | 638 | res = tipc_send2name(tport->ref, |
623 | &dest->addr.name.name, | 639 | &dest->addr.name.name, |
624 | dest->addr.name.domain, | 640 | dest->addr.name.domain, |
625 | m->msg_iovlen, | ||
626 | m->msg_iov, | 641 | m->msg_iov, |
627 | total_len); | 642 | total_len); |
628 | } else if (dest->addrtype == TIPC_ADDR_ID) { | 643 | } else if (dest->addrtype == TIPC_ADDR_ID) { |
629 | res = tipc_send2port(tport->ref, | 644 | res = tipc_send2port(tport->ref, |
630 | &dest->addr.id, | 645 | &dest->addr.id, |
631 | m->msg_iovlen, | ||
632 | m->msg_iov, | 646 | m->msg_iov, |
633 | total_len); | 647 | total_len); |
634 | } else if (dest->addrtype == TIPC_ADDR_MCAST) { | 648 | } else if (dest->addrtype == TIPC_ADDR_MCAST) { |
@@ -641,7 +655,6 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
641 | break; | 655 | break; |
642 | res = tipc_multicast(tport->ref, | 656 | res = tipc_multicast(tport->ref, |
643 | &dest->addr.nameseq, | 657 | &dest->addr.nameseq, |
644 | m->msg_iovlen, | ||
645 | m->msg_iov, | 658 | m->msg_iov, |
646 | total_len); | 659 | total_len); |
647 | } | 660 | } |
@@ -707,8 +720,7 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
707 | break; | 720 | break; |
708 | } | 721 | } |
709 | 722 | ||
710 | res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov, | 723 | res = tipc_send(tport->ref, m->msg_iov, total_len); |
711 | total_len); | ||
712 | if (likely(res != -ELINKCONG)) | 724 | if (likely(res != -ELINKCONG)) |
713 | break; | 725 | break; |
714 | if (timeout_val <= 0L) { | 726 | if (timeout_val <= 0L) { |
@@ -984,9 +996,6 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, | |||
984 | goto exit; | 996 | goto exit; |
985 | } | 997 | } |
986 | 998 | ||
987 | /* will be updated in set_orig_addr() if needed */ | ||
988 | m->msg_namelen = 0; | ||
989 | |||
990 | timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); | 999 | timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); |
991 | restart: | 1000 | restart: |
992 | 1001 | ||
@@ -1095,9 +1104,6 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, | |||
1095 | goto exit; | 1104 | goto exit; |
1096 | } | 1105 | } |
1097 | 1106 | ||
1098 | /* will be updated in set_orig_addr() if needed */ | ||
1099 | m->msg_namelen = 0; | ||
1100 | |||
1101 | target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); | 1107 | target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); |
1102 | timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); | 1108 | timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); |
1103 | 1109 | ||
@@ -1368,7 +1374,7 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf) | |||
1368 | return TIPC_ERR_OVERLOAD; | 1374 | return TIPC_ERR_OVERLOAD; |
1369 | 1375 | ||
1370 | /* Enqueue message */ | 1376 | /* Enqueue message */ |
1371 | TIPC_SKB_CB(buf)->handle = 0; | 1377 | TIPC_SKB_CB(buf)->handle = NULL; |
1372 | __skb_queue_tail(&sk->sk_receive_queue, buf); | 1378 | __skb_queue_tail(&sk->sk_receive_queue, buf); |
1373 | skb_set_owner_r(buf, sk); | 1379 | skb_set_owner_r(buf, sk); |
1374 | 1380 | ||
@@ -1691,7 +1697,7 @@ restart: | |||
1691 | /* Disconnect and send a 'FIN+' or 'FIN-' message to peer */ | 1697 | /* Disconnect and send a 'FIN+' or 'FIN-' message to peer */ |
1692 | buf = __skb_dequeue(&sk->sk_receive_queue); | 1698 | buf = __skb_dequeue(&sk->sk_receive_queue); |
1693 | if (buf) { | 1699 | if (buf) { |
1694 | if (TIPC_SKB_CB(buf)->handle != 0) { | 1700 | if (TIPC_SKB_CB(buf)->handle != NULL) { |
1695 | kfree_skb(buf); | 1701 | kfree_skb(buf); |
1696 | goto restart; | 1702 | goto restart; |
1697 | } | 1703 | } |