aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/link.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/link.c')
-rw-r--r--net/tipc/link.c167
1 files changed, 44 insertions, 123 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 0cc3d9015c5d..e8153f64d2d6 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 */
85struct 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
92static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, 78static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr,
93 struct sk_buff *buf); 79 struct sk_buff *buf);
94static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf); 80static 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,
97static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance); 83static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance);
98static int link_send_sections_long(struct tipc_port *sender, 84static 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);
102static void link_state_event(struct tipc_link *l_ptr, u32 event); 87static void link_state_event(struct tipc_link *l_ptr, u32 event);
103static void link_reset_statistics(struct tipc_link *l_ptr); 88static void link_reset_statistics(struct tipc_link *l_ptr);
104static void link_print(struct tipc_link *l_ptr, const char *str); 89static 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 */
170static 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 *
@@ -1065,8 +984,7 @@ static int link_send_buf_fast(struct tipc_link *l_ptr, struct sk_buff *buf,
1065 */ 984 */
1066int tipc_link_send_sections_fast(struct tipc_port *sender, 985int tipc_link_send_sections_fast(struct tipc_port *sender,
1067 struct iovec const *msg_sect, 986 struct iovec const *msg_sect,
1068 const u32 num_sect, unsigned int total_len, 987 unsigned int len, u32 destaddr)
1069 u32 destaddr)
1070{ 988{
1071 struct tipc_msg *hdr = &sender->phdr; 989 struct tipc_msg *hdr = &sender->phdr;
1072 struct tipc_link *l_ptr; 990 struct tipc_link *l_ptr;
@@ -1080,8 +998,7 @@ again:
1080 * Try building message using port's max_pkt hint. 998 * Try building message using port's max_pkt hint.
1081 * (Must not hold any locks while building message.) 999 * (Must not hold any locks while building message.)
1082 */ 1000 */
1083 res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, 1001 res = tipc_msg_build(hdr, msg_sect, len, sender->max_pkt, &buf);
1084 sender->max_pkt, &buf);
1085 /* Exit if build request was invalid */ 1002 /* Exit if build request was invalid */
1086 if (unlikely(res < 0)) 1003 if (unlikely(res < 0))
1087 return res; 1004 return res;
@@ -1121,8 +1038,7 @@ exit:
1121 if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt) 1038 if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt)
1122 goto again; 1039 goto again;
1123 1040
1124 return link_send_sections_long(sender, msg_sect, 1041 return link_send_sections_long(sender, msg_sect, len,
1125 num_sect, total_len,
1126 destaddr); 1042 destaddr);
1127 } 1043 }
1128 tipc_node_unlock(node); 1044 tipc_node_unlock(node);
@@ -1133,8 +1049,8 @@ exit:
1133 if (buf) 1049 if (buf)
1134 return tipc_reject_msg(buf, TIPC_ERR_NO_NODE); 1050 return tipc_reject_msg(buf, TIPC_ERR_NO_NODE);
1135 if (res >= 0) 1051 if (res >= 0)
1136 return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect, 1052 return tipc_port_reject_sections(sender, hdr, msg_sect,
1137 total_len, TIPC_ERR_NO_NODE); 1053 len, TIPC_ERR_NO_NODE);
1138 return res; 1054 return res;
1139} 1055}
1140 1056
@@ -1154,18 +1070,17 @@ exit:
1154 */ 1070 */
1155static int link_send_sections_long(struct tipc_port *sender, 1071static int link_send_sections_long(struct tipc_port *sender,
1156 struct iovec const *msg_sect, 1072 struct iovec const *msg_sect,
1157 u32 num_sect, unsigned int total_len, 1073 unsigned int len, u32 destaddr)
1158 u32 destaddr)
1159{ 1074{
1160 struct tipc_link *l_ptr; 1075 struct tipc_link *l_ptr;
1161 struct tipc_node *node; 1076 struct tipc_node *node;
1162 struct tipc_msg *hdr = &sender->phdr; 1077 struct tipc_msg *hdr = &sender->phdr;
1163 u32 dsz = total_len; 1078 u32 dsz = len;
1164 u32 max_pkt, fragm_sz, rest; 1079 u32 max_pkt, fragm_sz, rest;
1165 struct tipc_msg fragm_hdr; 1080 struct tipc_msg fragm_hdr;
1166 struct sk_buff *buf, *buf_chain, *prev; 1081 struct sk_buff *buf, *buf_chain, *prev;
1167 u32 fragm_crs, fragm_rest, hsz, sect_rest; 1082 u32 fragm_crs, fragm_rest, hsz, sect_rest;
1168 const unchar *sect_crs; 1083 const unchar __user *sect_crs;
1169 int curr_sect; 1084 int curr_sect;
1170 u32 fragm_no; 1085 u32 fragm_no;
1171 int res = 0; 1086 int res = 0;
@@ -1207,7 +1122,7 @@ again:
1207 1122
1208 if (!sect_rest) { 1123 if (!sect_rest) {
1209 sect_rest = msg_sect[++curr_sect].iov_len; 1124 sect_rest = msg_sect[++curr_sect].iov_len;
1210 sect_crs = (const unchar *)msg_sect[curr_sect].iov_base; 1125 sect_crs = msg_sect[curr_sect].iov_base;
1211 } 1126 }
1212 1127
1213 if (sect_rest < fragm_rest) 1128 if (sect_rest < fragm_rest)
@@ -1283,8 +1198,8 @@ reject:
1283 buf = buf_chain->next; 1198 buf = buf_chain->next;
1284 kfree_skb(buf_chain); 1199 kfree_skb(buf_chain);
1285 } 1200 }
1286 return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect, 1201 return tipc_port_reject_sections(sender, hdr, msg_sect,
1287 total_len, TIPC_ERR_NO_NODE); 1202 len, TIPC_ERR_NO_NODE);
1288 } 1203 }
1289 1204
1290 /* Append chain of fragments to send queue & send them */ 1205 /* Append chain of fragments to send queue & send them */
@@ -2585,25 +2500,21 @@ void tipc_link_set_queue_limits(struct tipc_link *l_ptr, u32 window)
2585static struct tipc_link *link_find_link(const char *name, 2500static struct tipc_link *link_find_link(const char *name,
2586 struct tipc_node **node) 2501 struct tipc_node **node)
2587{ 2502{
2588 struct tipc_link_name link_name_parts;
2589 struct tipc_bearer *b_ptr;
2590 struct tipc_link *l_ptr; 2503 struct tipc_link *l_ptr;
2504 struct tipc_node *n_ptr;
2505 int i;
2591 2506
2592 if (!link_name_validate(name, &link_name_parts)) 2507 list_for_each_entry(n_ptr, &tipc_node_list, list) {
2593 return NULL; 2508 for (i = 0; i < MAX_BEARERS; i++) {
2594 2509 l_ptr = n_ptr->links[i];
2595 b_ptr = tipc_bearer_find_interface(link_name_parts.if_local); 2510 if (l_ptr && !strcmp(l_ptr->name, name))
2596 if (!b_ptr) 2511 goto found;
2597 return NULL; 2512 }
2598 2513 }
2599 *node = tipc_node_find(link_name_parts.addr_peer); 2514 l_ptr = NULL;
2600 if (!*node) 2515 n_ptr = NULL;
2601 return NULL; 2516found:
2602 2517 *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; 2518 return l_ptr;
2608} 2519}
2609 2520
@@ -2646,6 +2557,7 @@ static int link_cmd_set_value(const char *name, u32 new_value, u16 cmd)
2646 struct tipc_link *l_ptr; 2557 struct tipc_link *l_ptr;
2647 struct tipc_bearer *b_ptr; 2558 struct tipc_bearer *b_ptr;
2648 struct tipc_media *m_ptr; 2559 struct tipc_media *m_ptr;
2560 int res = 0;
2649 2561
2650 l_ptr = link_find_link(name, &node); 2562 l_ptr = link_find_link(name, &node);
2651 if (l_ptr) { 2563 if (l_ptr) {
@@ -2668,9 +2580,12 @@ static int link_cmd_set_value(const char *name, u32 new_value, u16 cmd)
2668 case TIPC_CMD_SET_LINK_WINDOW: 2580 case TIPC_CMD_SET_LINK_WINDOW:
2669 tipc_link_set_queue_limits(l_ptr, new_value); 2581 tipc_link_set_queue_limits(l_ptr, new_value);
2670 break; 2582 break;
2583 default:
2584 res = -EINVAL;
2585 break;
2671 } 2586 }
2672 tipc_node_unlock(node); 2587 tipc_node_unlock(node);
2673 return 0; 2588 return res;
2674 } 2589 }
2675 2590
2676 b_ptr = tipc_bearer_find(name); 2591 b_ptr = tipc_bearer_find(name);
@@ -2678,15 +2593,18 @@ static int link_cmd_set_value(const char *name, u32 new_value, u16 cmd)
2678 switch (cmd) { 2593 switch (cmd) {
2679 case TIPC_CMD_SET_LINK_TOL: 2594 case TIPC_CMD_SET_LINK_TOL:
2680 b_ptr->tolerance = new_value; 2595 b_ptr->tolerance = new_value;
2681 return 0; 2596 break;
2682 case TIPC_CMD_SET_LINK_PRI: 2597 case TIPC_CMD_SET_LINK_PRI:
2683 b_ptr->priority = new_value; 2598 b_ptr->priority = new_value;
2684 return 0; 2599 break;
2685 case TIPC_CMD_SET_LINK_WINDOW: 2600 case TIPC_CMD_SET_LINK_WINDOW:
2686 b_ptr->window = new_value; 2601 b_ptr->window = new_value;
2687 return 0; 2602 break;
2603 default:
2604 res = -EINVAL;
2605 break;
2688 } 2606 }
2689 return -EINVAL; 2607 return res;
2690 } 2608 }
2691 2609
2692 m_ptr = tipc_media_find(name); 2610 m_ptr = tipc_media_find(name);
@@ -2695,15 +2613,18 @@ static int link_cmd_set_value(const char *name, u32 new_value, u16 cmd)
2695 switch (cmd) { 2613 switch (cmd) {
2696 case TIPC_CMD_SET_LINK_TOL: 2614 case TIPC_CMD_SET_LINK_TOL:
2697 m_ptr->tolerance = new_value; 2615 m_ptr->tolerance = new_value;
2698 return 0; 2616 break;
2699 case TIPC_CMD_SET_LINK_PRI: 2617 case TIPC_CMD_SET_LINK_PRI:
2700 m_ptr->priority = new_value; 2618 m_ptr->priority = new_value;
2701 return 0; 2619 break;
2702 case TIPC_CMD_SET_LINK_WINDOW: 2620 case TIPC_CMD_SET_LINK_WINDOW:
2703 m_ptr->window = new_value; 2621 m_ptr->window = new_value;
2704 return 0; 2622 break;
2623 default:
2624 res = -EINVAL;
2625 break;
2705 } 2626 }
2706 return -EINVAL; 2627 return res;
2707} 2628}
2708 2629
2709struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space, 2630struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space,