diff options
Diffstat (limited to 'net/tipc/link.c')
-rw-r--r-- | net/tipc/link.c | 167 |
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 | */ | ||
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 | * |
@@ -1065,8 +984,7 @@ static int link_send_buf_fast(struct tipc_link *l_ptr, struct sk_buff *buf, | |||
1065 | */ | 984 | */ |
1066 | int tipc_link_send_sections_fast(struct tipc_port *sender, | 985 | int 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 | */ |
1155 | static int link_send_sections_long(struct tipc_port *sender, | 1071 | static 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) | |||
2585 | static struct tipc_link *link_find_link(const char *name, | 2500 | static 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; | 2516 | found: |
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 | ||
2709 | struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space, | 2630 | struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space, |