diff options
Diffstat (limited to 'net/tipc/udp_media.c')
-rw-r--r-- | net/tipc/udp_media.c | 44 |
1 files changed, 23 insertions, 21 deletions
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c index d63a911e7fe2..c9cf2be3674a 100644 --- a/net/tipc/udp_media.c +++ b/net/tipc/udp_media.c | |||
@@ -48,19 +48,12 @@ | |||
48 | #include <linux/tipc_netlink.h> | 48 | #include <linux/tipc_netlink.h> |
49 | #include "core.h" | 49 | #include "core.h" |
50 | #include "bearer.h" | 50 | #include "bearer.h" |
51 | #include "netlink.h" | ||
51 | 52 | ||
52 | /* IANA assigned UDP port */ | 53 | /* IANA assigned UDP port */ |
53 | #define UDP_PORT_DEFAULT 6118 | 54 | #define UDP_PORT_DEFAULT 6118 |
54 | 55 | ||
55 | #define UDP_MIN_HEADROOM 28 | 56 | #define UDP_MIN_HEADROOM 48 |
56 | |||
57 | static const struct nla_policy tipc_nl_udp_policy[TIPC_NLA_UDP_MAX + 1] = { | ||
58 | [TIPC_NLA_UDP_UNSPEC] = {.type = NLA_UNSPEC}, | ||
59 | [TIPC_NLA_UDP_LOCAL] = {.type = NLA_BINARY, | ||
60 | .len = sizeof(struct sockaddr_storage)}, | ||
61 | [TIPC_NLA_UDP_REMOTE] = {.type = NLA_BINARY, | ||
62 | .len = sizeof(struct sockaddr_storage)}, | ||
63 | }; | ||
64 | 57 | ||
65 | /** | 58 | /** |
66 | * struct udp_media_addr - IP/UDP addressing information | 59 | * struct udp_media_addr - IP/UDP addressing information |
@@ -181,6 +174,8 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb, | |||
181 | err = PTR_ERR(rt); | 174 | err = PTR_ERR(rt); |
182 | goto tx_error; | 175 | goto tx_error; |
183 | } | 176 | } |
177 | |||
178 | skb->dev = rt->dst.dev; | ||
184 | ttl = ip4_dst_hoplimit(&rt->dst); | 179 | ttl = ip4_dst_hoplimit(&rt->dst); |
185 | udp_tunnel_xmit_skb(rt, ub->ubsock->sk, skb, src->ipv4.s_addr, | 180 | udp_tunnel_xmit_skb(rt, ub->ubsock->sk, skb, src->ipv4.s_addr, |
186 | dst->ipv4.s_addr, 0, ttl, 0, src->udp_port, | 181 | dst->ipv4.s_addr, 0, ttl, 0, src->udp_port, |
@@ -201,7 +196,7 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb, | |||
201 | ttl = ip6_dst_hoplimit(ndst); | 196 | ttl = ip6_dst_hoplimit(ndst); |
202 | err = udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, | 197 | err = udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, |
203 | ndst->dev, &src->ipv6, | 198 | ndst->dev, &src->ipv6, |
204 | &dst->ipv6, 0, ttl, src->udp_port, | 199 | &dst->ipv6, 0, ttl, 0, src->udp_port, |
205 | dst->udp_port, false); | 200 | dst->udp_port, false); |
206 | #endif | 201 | #endif |
207 | } | 202 | } |
@@ -274,7 +269,7 @@ static int parse_options(struct nlattr *attrs[], struct udp_bearer *ub, | |||
274 | struct udp_media_addr *remote) | 269 | struct udp_media_addr *remote) |
275 | { | 270 | { |
276 | struct nlattr *opts[TIPC_NLA_UDP_MAX + 1]; | 271 | struct nlattr *opts[TIPC_NLA_UDP_MAX + 1]; |
277 | struct sockaddr_storage *sa_local, *sa_remote; | 272 | struct sockaddr_storage sa_local, sa_remote; |
278 | 273 | ||
279 | if (!attrs[TIPC_NLA_BEARER_UDP_OPTS]) | 274 | if (!attrs[TIPC_NLA_BEARER_UDP_OPTS]) |
280 | goto err; | 275 | goto err; |
@@ -283,41 +278,48 @@ static int parse_options(struct nlattr *attrs[], struct udp_bearer *ub, | |||
283 | tipc_nl_udp_policy)) | 278 | tipc_nl_udp_policy)) |
284 | goto err; | 279 | goto err; |
285 | if (opts[TIPC_NLA_UDP_LOCAL] && opts[TIPC_NLA_UDP_REMOTE]) { | 280 | if (opts[TIPC_NLA_UDP_LOCAL] && opts[TIPC_NLA_UDP_REMOTE]) { |
286 | sa_local = nla_data(opts[TIPC_NLA_UDP_LOCAL]); | 281 | nla_memcpy(&sa_local, opts[TIPC_NLA_UDP_LOCAL], |
287 | sa_remote = nla_data(opts[TIPC_NLA_UDP_REMOTE]); | 282 | sizeof(sa_local)); |
283 | nla_memcpy(&sa_remote, opts[TIPC_NLA_UDP_REMOTE], | ||
284 | sizeof(sa_remote)); | ||
288 | } else { | 285 | } else { |
289 | err: | 286 | err: |
290 | pr_err("Invalid UDP bearer configuration"); | 287 | pr_err("Invalid UDP bearer configuration"); |
291 | return -EINVAL; | 288 | return -EINVAL; |
292 | } | 289 | } |
293 | if ((sa_local->ss_family & sa_remote->ss_family) == AF_INET) { | 290 | if ((sa_local.ss_family & sa_remote.ss_family) == AF_INET) { |
294 | struct sockaddr_in *ip4; | 291 | struct sockaddr_in *ip4; |
295 | 292 | ||
296 | ip4 = (struct sockaddr_in *)sa_local; | 293 | ip4 = (struct sockaddr_in *)&sa_local; |
297 | local->proto = htons(ETH_P_IP); | 294 | local->proto = htons(ETH_P_IP); |
298 | local->udp_port = ip4->sin_port; | 295 | local->udp_port = ip4->sin_port; |
299 | local->ipv4.s_addr = ip4->sin_addr.s_addr; | 296 | local->ipv4.s_addr = ip4->sin_addr.s_addr; |
300 | 297 | ||
301 | ip4 = (struct sockaddr_in *)sa_remote; | 298 | ip4 = (struct sockaddr_in *)&sa_remote; |
302 | remote->proto = htons(ETH_P_IP); | 299 | remote->proto = htons(ETH_P_IP); |
303 | remote->udp_port = ip4->sin_port; | 300 | remote->udp_port = ip4->sin_port; |
304 | remote->ipv4.s_addr = ip4->sin_addr.s_addr; | 301 | remote->ipv4.s_addr = ip4->sin_addr.s_addr; |
305 | return 0; | 302 | return 0; |
306 | 303 | ||
307 | #if IS_ENABLED(CONFIG_IPV6) | 304 | #if IS_ENABLED(CONFIG_IPV6) |
308 | } else if ((sa_local->ss_family & sa_remote->ss_family) == AF_INET6) { | 305 | } else if ((sa_local.ss_family & sa_remote.ss_family) == AF_INET6) { |
306 | int atype; | ||
309 | struct sockaddr_in6 *ip6; | 307 | struct sockaddr_in6 *ip6; |
310 | 308 | ||
311 | ip6 = (struct sockaddr_in6 *)sa_local; | 309 | ip6 = (struct sockaddr_in6 *)&sa_local; |
310 | atype = ipv6_addr_type(&ip6->sin6_addr); | ||
311 | if (__ipv6_addr_needs_scope_id(atype) && !ip6->sin6_scope_id) | ||
312 | return -EINVAL; | ||
313 | |||
312 | local->proto = htons(ETH_P_IPV6); | 314 | local->proto = htons(ETH_P_IPV6); |
313 | local->udp_port = ip6->sin6_port; | 315 | local->udp_port = ip6->sin6_port; |
314 | local->ipv6 = ip6->sin6_addr; | 316 | memcpy(&local->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr)); |
315 | ub->ifindex = ip6->sin6_scope_id; | 317 | ub->ifindex = ip6->sin6_scope_id; |
316 | 318 | ||
317 | ip6 = (struct sockaddr_in6 *)sa_remote; | 319 | ip6 = (struct sockaddr_in6 *)&sa_remote; |
318 | remote->proto = htons(ETH_P_IPV6); | 320 | remote->proto = htons(ETH_P_IPV6); |
319 | remote->udp_port = ip6->sin6_port; | 321 | remote->udp_port = ip6->sin6_port; |
320 | remote->ipv6 = ip6->sin6_addr; | 322 | memcpy(&remote->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr)); |
321 | return 0; | 323 | return 0; |
322 | #endif | 324 | #endif |
323 | } | 325 | } |