diff options
| author | David S. Miller <davem@davemloft.net> | 2013-10-18 13:22:19 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2013-10-18 13:22:19 -0400 |
| commit | ace0d5d8bf8a69866e4394ca2e4c5d1296ef7db2 (patch) | |
| tree | d12bae2180f77b4dc48580bf5a85b995f1f4909c /net/tipc/link.c | |
| parent | 7cc7c5e54b7128195a1403747a63971c3c3f8e25 (diff) | |
| parent | bbfbe47cc99ce093708aaf28b7f2c08d28045c67 (diff) | |
Merge branch 'tipc'
Jon Maloy says:
====================
Some small and relatively straightforward patches. With exception of
the two first ones they are all unrelated and address minor issues.
v2: update of v1 (http://patchwork.ozlabs.org/patch/277404/)
-added commit to use memcpy_fromiovec on user data as per v1 feedback
-updated sparse fix commit to drop chunks covered by above commit
-added new commit that greatly simplifies the link lookup routine
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
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, |
