udp_media.c 21.6 KB
Newer Older
E
Erik Hugne 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
/* net/tipc/udp_media.c: IP bearer support for TIPC
 *
 * Copyright (c) 2015, Ericsson AB
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the names of the copyright holders nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <linux/socket.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/inet.h>
#include <linux/inetdevice.h>
#include <linux/igmp.h>
#include <linux/kernel.h>
#include <linux/workqueue.h>
#include <linux/list.h>
#include <net/sock.h>
#include <net/ip.h>
#include <net/udp_tunnel.h>
47
#include <net/ipv6_stubs.h>
E
Erik Hugne 已提交
48 49
#include <linux/tipc_netlink.h>
#include "core.h"
50 51
#include "addr.h"
#include "net.h"
E
Erik Hugne 已提交
52
#include "bearer.h"
53
#include "netlink.h"
R
Richard Alpe 已提交
54
#include "msg.h"
55
#include "udp_media.h"
E
Erik Hugne 已提交
56 57 58 59

/* IANA assigned UDP port */
#define UDP_PORT_DEFAULT	6118

60
#define UDP_MIN_HEADROOM        48
61

E
Erik Hugne 已提交
62 63 64 65 66
/**
 * struct udp_media_addr - IP/UDP addressing information
 *
 * This is the bearer level originating address used in neighbor discovery
 * messages, and all fields should be in network byte order
67 68 69 70 71
 *
 * @proto: Ethernet protocol in use
 * @port: port being used
 * @ipv4: IPv4 address of neighbor
 * @ipv6: IPv6 address of neighbor
E
Erik Hugne 已提交
72 73 74
 */
struct udp_media_addr {
	__be16	proto;
75
	__be16	port;
E
Erik Hugne 已提交
76 77 78 79 80 81
	union {
		struct in_addr ipv4;
		struct in6_addr ipv6;
	};
};

R
Richard Alpe 已提交
82 83 84
/* struct udp_replicast - container for UDP remote addresses */
struct udp_replicast {
	struct udp_media_addr addr;
85
	struct dst_cache dst_cache;
R
Richard Alpe 已提交
86 87 88 89
	struct rcu_head rcu;
	struct list_head list;
};

E
Erik Hugne 已提交
90 91 92 93 94 95
/**
 * struct udp_bearer - ip/udp bearer data structure
 * @bearer:	associated generic tipc bearer
 * @ubsock:	bearer associated socket
 * @ifindex:	local address scope
 * @work:	used to schedule deferred work on a bearer
96
 * @rcast:	associated udp_replicast container
E
Erik Hugne 已提交
97 98 99 100 101 102
 */
struct udp_bearer {
	struct tipc_bearer __rcu *bearer;
	struct socket *ubsock;
	u32 ifindex;
	struct work_struct work;
R
Richard Alpe 已提交
103
	struct udp_replicast rcast;
E
Erik Hugne 已提交
104 105
};

R
Richard Alpe 已提交
106 107 108 109 110 111 112 113 114 115 116
static int tipc_udp_is_mcast_addr(struct udp_media_addr *addr)
{
	if (ntohs(addr->proto) == ETH_P_IP)
		return ipv4_is_multicast(addr->ipv4.s_addr);
#if IS_ENABLED(CONFIG_IPV6)
	else
		return ipv6_addr_is_multicast(&addr->ipv6);
#endif
	return 0;
}

E
Erik Hugne 已提交
117 118 119 120 121 122 123
/* udp_media_addr_set - convert a ip/udp address to a TIPC media address */
static void tipc_udp_media_addr_set(struct tipc_media_addr *addr,
				    struct udp_media_addr *ua)
{
	memset(addr, 0, sizeof(struct tipc_media_addr));
	addr->media_id = TIPC_MEDIA_TYPE_UDP;
	memcpy(addr->value, ua, sizeof(struct udp_media_addr));
R
Richard Alpe 已提交
124 125

	if (tipc_udp_is_mcast_addr(ua))
126
		addr->broadcast = TIPC_BROADCAST_SUPPORT;
E
Erik Hugne 已提交
127 128 129 130 131 132 133 134
}

/* tipc_udp_addr2str - convert ip/udp address to string */
static int tipc_udp_addr2str(struct tipc_media_addr *a, char *buf, int size)
{
	struct udp_media_addr *ua = (struct udp_media_addr *)&a->value;

	if (ntohs(ua->proto) == ETH_P_IP)
135
		snprintf(buf, size, "%pI4:%u", &ua->ipv4, ntohs(ua->port));
E
Erik Hugne 已提交
136
	else if (ntohs(ua->proto) == ETH_P_IPV6)
137
		snprintf(buf, size, "%pI6:%u", &ua->ipv6, ntohs(ua->port));
E
Erik Hugne 已提交
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
	else
		pr_err("Invalid UDP media address\n");
	return 0;
}

/* tipc_udp_msg2addr - extract an ip/udp address from a TIPC ndisc message */
static int tipc_udp_msg2addr(struct tipc_bearer *b, struct tipc_media_addr *a,
			     char *msg)
{
	struct udp_media_addr *ua;

	ua = (struct udp_media_addr *) (msg + TIPC_MEDIA_ADDR_OFFSET);
	if (msg[TIPC_MEDIA_TYPE_OFFSET] != TIPC_MEDIA_TYPE_UDP)
		return -EINVAL;
	tipc_udp_media_addr_set(a, ua);
	return 0;
}

/* tipc_udp_addr2msg - write an ip/udp address to a TIPC ndisc message */
static int tipc_udp_addr2msg(char *msg, struct tipc_media_addr *a)
{
	memset(msg, 0, TIPC_MEDIA_INFO_SIZE);
	msg[TIPC_MEDIA_TYPE_OFFSET] = TIPC_MEDIA_TYPE_UDP;
	memcpy(msg + TIPC_MEDIA_ADDR_OFFSET, a->value,
	       sizeof(struct udp_media_addr));
	return 0;
}

/* tipc_send_msg - enqueue a send request */
R
Richard Alpe 已提交
167 168
static int tipc_udp_xmit(struct net *net, struct sk_buff *skb,
			 struct udp_bearer *ub, struct udp_media_addr *src,
169
			 struct udp_media_addr *dst, struct dst_cache *cache)
E
Erik Hugne 已提交
170
{
171
	struct dst_entry *ndst;
E
Erik Hugne 已提交
172 173
	int ttl, err = 0;

174 175
	local_bh_disable();
	ndst = dst_cache_get(cache);
176
	if (dst->proto == htons(ETH_P_IP)) {
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
		struct rtable *rt = (struct rtable *)ndst;

		if (!rt) {
			struct flowi4 fl = {
				.daddr = dst->ipv4.s_addr,
				.saddr = src->ipv4.s_addr,
				.flowi4_mark = skb->mark,
				.flowi4_proto = IPPROTO_UDP
			};
			rt = ip_route_output_key(net, &fl);
			if (IS_ERR(rt)) {
				err = PTR_ERR(rt);
				goto tx_error;
			}
			dst_cache_set_ip4(cache, &rt->dst, fl.saddr);
E
Erik Hugne 已提交
192
		}
193

E
Erik Hugne 已提交
194
		ttl = ip4_dst_hoplimit(&rt->dst);
195
		udp_tunnel_xmit_skb(rt, ub->ubsock->sk, skb, src->ipv4.s_addr,
196 197
				    dst->ipv4.s_addr, 0, ttl, 0, src->port,
				    dst->port, false, true);
E
Erik Hugne 已提交
198 199
#if IS_ENABLED(CONFIG_IPV6)
	} else {
200 201 202 203 204 205 206
		if (!ndst) {
			struct flowi6 fl6 = {
				.flowi6_oif = ub->ifindex,
				.daddr = dst->ipv6,
				.saddr = src->ipv6,
				.flowi6_proto = IPPROTO_UDP
			};
207 208 209 210 211
			ndst = ipv6_stub->ipv6_dst_lookup_flow(net,
							       ub->ubsock->sk,
							       &fl6, NULL);
			if (IS_ERR(ndst)) {
				err = PTR_ERR(ndst);
212
				goto tx_error;
213
			}
214 215
			dst_cache_set_ip6(cache, ndst, &fl6.saddr);
		}
E
Erik Hugne 已提交
216
		ttl = ip6_dst_hoplimit(ndst);
217 218 219
		err = udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, NULL,
					   &src->ipv6, &dst->ipv6, 0, ttl, 0,
					   src->port, dst->port, false);
E
Erik Hugne 已提交
220 221
#endif
	}
222
	local_bh_enable();
E
Erik Hugne 已提交
223 224 225
	return err;

tx_error:
226
	local_bh_enable();
227
	kfree_skb(skb);
E
Erik Hugne 已提交
228 229 230
	return err;
}

R
Richard Alpe 已提交
231 232 233 234 235 236
static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb,
			     struct tipc_bearer *b,
			     struct tipc_media_addr *addr)
{
	struct udp_media_addr *src = (struct udp_media_addr *)&b->addr.value;
	struct udp_media_addr *dst = (struct udp_media_addr *)&addr->value;
R
Richard Alpe 已提交
237
	struct udp_replicast *rcast;
R
Richard Alpe 已提交
238 239 240 241 242 243
	struct udp_bearer *ub;
	int err = 0;

	if (skb_headroom(skb) < UDP_MIN_HEADROOM) {
		err = pskb_expand_head(skb, UDP_MIN_HEADROOM, 0, GFP_ATOMIC);
		if (err)
R
Richard Alpe 已提交
244
			goto out;
R
Richard Alpe 已提交
245 246 247
	}

	skb_set_inner_protocol(skb, htons(ETH_P_TIPC));
248
	ub = rcu_dereference(b->media_ptr);
R
Richard Alpe 已提交
249 250
	if (!ub) {
		err = -ENODEV;
R
Richard Alpe 已提交
251
		goto out;
R
Richard Alpe 已提交
252 253
	}

254
	if (addr->broadcast != TIPC_REPLICAST_SUPPORT)
255 256
		return tipc_udp_xmit(net, skb, ub, src, dst,
				     &ub->rcast.dst_cache);
R
Richard Alpe 已提交
257

R
Richard Alpe 已提交
258 259 260 261 262 263 264 265 266 267
	/* Replicast, send an skb to each configured IP address */
	list_for_each_entry_rcu(rcast, &ub->rcast.list, list) {
		struct sk_buff *_skb;

		_skb = pskb_copy(skb, GFP_ATOMIC);
		if (!_skb) {
			err = -ENOMEM;
			goto out;
		}

268 269
		err = tipc_udp_xmit(net, _skb, ub, src, &rcast->addr,
				    &rcast->dst_cache);
C
Cong Wang 已提交
270
		if (err)
R
Richard Alpe 已提交
271 272 273 274
			goto out;
	}
	err = 0;
out:
R
Richard Alpe 已提交
275 276 277 278
	kfree_skb(skb);
	return err;
}

279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
static bool tipc_udp_is_known_peer(struct tipc_bearer *b,
				   struct udp_media_addr *addr)
{
	struct udp_replicast *rcast, *tmp;
	struct udp_bearer *ub;

	ub = rcu_dereference_rtnl(b->media_ptr);
	if (!ub) {
		pr_err_ratelimited("UDP bearer instance not found\n");
		return false;
	}

	list_for_each_entry_safe(rcast, tmp, &ub->rcast.list, list) {
		if (!memcmp(&rcast->addr, addr, sizeof(struct udp_media_addr)))
			return true;
	}

	return false;
}

R
Richard Alpe 已提交
299 300 301 302 303 304 305 306 307 308 309 310 311 312
static int tipc_udp_rcast_add(struct tipc_bearer *b,
			      struct udp_media_addr *addr)
{
	struct udp_replicast *rcast;
	struct udp_bearer *ub;

	ub = rcu_dereference_rtnl(b->media_ptr);
	if (!ub)
		return -ENODEV;

	rcast = kmalloc(sizeof(*rcast), GFP_ATOMIC);
	if (!rcast)
		return -ENOMEM;

313 314 315 316 317
	if (dst_cache_init(&rcast->dst_cache, GFP_ATOMIC)) {
		kfree(rcast);
		return -ENOMEM;
	}

R
Richard Alpe 已提交
318 319 320 321 322 323 324 325
	memcpy(&rcast->addr, addr, sizeof(struct udp_media_addr));

	if (ntohs(addr->proto) == ETH_P_IP)
		pr_info("New replicast peer: %pI4\n", &rcast->addr.ipv4);
#if IS_ENABLED(CONFIG_IPV6)
	else if (ntohs(addr->proto) == ETH_P_IPV6)
		pr_info("New replicast peer: %pI6\n", &rcast->addr.ipv6);
#endif
326
	b->bcast_addr.broadcast = TIPC_REPLICAST_SUPPORT;
R
Richard Alpe 已提交
327 328 329 330
	list_add_rcu(&rcast->list, &ub->rcast.list);
	return 0;
}

331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
static int tipc_udp_rcast_disc(struct tipc_bearer *b, struct sk_buff *skb)
{
	struct udp_media_addr src = {0};
	struct udp_media_addr *dst;

	dst = (struct udp_media_addr *)&b->bcast_addr.value;
	if (tipc_udp_is_mcast_addr(dst))
		return 0;

	src.port = udp_hdr(skb)->source;

	if (ip_hdr(skb)->version == 4) {
		struct iphdr *iphdr = ip_hdr(skb);

		src.proto = htons(ETH_P_IP);
		src.ipv4.s_addr = iphdr->saddr;
		if (ipv4_is_multicast(iphdr->daddr))
			return 0;
#if IS_ENABLED(CONFIG_IPV6)
	} else if (ip_hdr(skb)->version == 6) {
		struct ipv6hdr *iphdr = ipv6_hdr(skb);

		src.proto = htons(ETH_P_IPV6);
		src.ipv6 = iphdr->saddr;
		if (ipv6_addr_is_multicast(&iphdr->daddr))
			return 0;
#endif
	} else {
		return 0;
	}

	if (likely(tipc_udp_is_known_peer(b, &src)))
		return 0;

	return tipc_udp_rcast_add(b, &src);
}

E
Erik Hugne 已提交
368 369 370 371 372
/* tipc_udp_recv - read data from bearer socket */
static int tipc_udp_recv(struct sock *sk, struct sk_buff *skb)
{
	struct udp_bearer *ub;
	struct tipc_bearer *b;
373 374
	struct tipc_msg *hdr;
	int err;
E
Erik Hugne 已提交
375 376 377 378

	ub = rcu_dereference_sk_user_data(sk);
	if (!ub) {
		pr_err_ratelimited("Failed to get UDP bearer reference");
379
		goto out;
E
Erik Hugne 已提交
380 381
	}
	skb_pull(skb, sizeof(struct udphdr));
382 383
	hdr = buf_msg(skb);

384
	b = rcu_dereference(ub->bearer);
385
	if (!b)
386
		goto out;
E
Erik Hugne 已提交
387

388
	if (b && test_bit(0, &b->up)) {
389
		TIPC_SKB_CB(skb)->flags = 0;
E
Erik Hugne 已提交
390 391 392
		tipc_rcv(sock_net(sk), skb, b);
		return 0;
	}
393 394 395 396

	if (unlikely(msg_user(hdr) == LINK_CONFIG)) {
		err = tipc_udp_rcast_disc(b, skb);
		if (err)
397
			goto out;
398 399 400
	}

out:
E
Erik Hugne 已提交
401 402 403 404 405 406 407 408 409 410 411 412 413
	kfree_skb(skb);
	return 0;
}

static int enable_mcast(struct udp_bearer *ub, struct udp_media_addr *remote)
{
	int err = 0;
	struct ip_mreqn mreqn;
	struct sock *sk = ub->ubsock->sk;

	if (ntohs(remote->proto) == ETH_P_IP) {
		mreqn.imr_multiaddr = remote->ipv4;
		mreqn.imr_ifindex = ub->ifindex;
414
		err = ip_mc_join_group(sk, &mreqn);
415
#if IS_ENABLED(CONFIG_IPV6)
E
Erik Hugne 已提交
416
	} else {
417
		lock_sock(sk);
418 419
		err = ipv6_stub->ipv6_sock_mc_join(sk, ub->ifindex,
						   &remote->ipv6);
420
		release_sock(sk);
421
#endif
E
Erik Hugne 已提交
422 423 424 425
	}
	return err;
}

426 427 428 429 430 431
static int __tipc_nl_add_udp_addr(struct sk_buff *skb,
				  struct udp_media_addr *addr, int nla_t)
{
	if (ntohs(addr->proto) == ETH_P_IP) {
		struct sockaddr_in ip4;

432
		memset(&ip4, 0, sizeof(ip4));
433 434 435 436 437 438 439 440 441 442
		ip4.sin_family = AF_INET;
		ip4.sin_port = addr->port;
		ip4.sin_addr.s_addr = addr->ipv4.s_addr;
		if (nla_put(skb, nla_t, sizeof(ip4), &ip4))
			return -EMSGSIZE;

#if IS_ENABLED(CONFIG_IPV6)
	} else if (ntohs(addr->proto) == ETH_P_IPV6) {
		struct sockaddr_in6 ip6;

443
		memset(&ip6, 0, sizeof(ip6));
444 445 446 447 448 449 450 451 452 453 454
		ip6.sin6_family = AF_INET6;
		ip6.sin6_port  = addr->port;
		memcpy(&ip6.sin6_addr, &addr->ipv6, sizeof(struct in6_addr));
		if (nla_put(skb, nla_t, sizeof(ip6), &ip6))
			return -EMSGSIZE;
#endif
	}

	return 0;
}

455 456 457 458 459 460 461 462 463 464 465 466 467
int tipc_udp_nl_dump_remoteip(struct sk_buff *skb, struct netlink_callback *cb)
{
	u32 bid = cb->args[0];
	u32 skip_cnt = cb->args[1];
	u32 portid = NETLINK_CB(cb->skb).portid;
	struct udp_replicast *rcast, *tmp;
	struct tipc_bearer *b;
	struct udp_bearer *ub;
	void *hdr;
	int err;
	int i;

	if (!bid && !skip_cnt) {
468
		struct nlattr **attrs = genl_dumpit_info(cb)->attrs;
469 470 471 472 473 474 475
		struct net *net = sock_net(skb->sk);
		struct nlattr *battrs[TIPC_NLA_BEARER_MAX + 1];
		char *bname;

		if (!attrs[TIPC_NLA_BEARER])
			return -EINVAL;

476 477 478
		err = nla_parse_nested_deprecated(battrs, TIPC_NLA_BEARER_MAX,
						  attrs[TIPC_NLA_BEARER],
						  tipc_nl_bearer_policy, NULL);
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
		if (err)
			return err;

		if (!battrs[TIPC_NLA_BEARER_NAME])
			return -EINVAL;

		bname = nla_data(battrs[TIPC_NLA_BEARER_NAME]);

		rtnl_lock();
		b = tipc_bearer_find(net, bname);
		if (!b) {
			rtnl_unlock();
			return -EINVAL;
		}
		bid = b->identity;
	} else {
		struct net *net = sock_net(skb->sk);
		struct tipc_net *tn = net_generic(net, tipc_net_id);

		rtnl_lock();
		b = rtnl_dereference(tn->bearer_list[bid]);
		if (!b) {
			rtnl_unlock();
			return -EINVAL;
		}
	}

506
	ub = rtnl_dereference(b->media_ptr);
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
	if (!ub) {
		rtnl_unlock();
		return -EINVAL;
	}

	i = 0;
	list_for_each_entry_safe(rcast, tmp, &ub->rcast.list, list) {
		if (i < skip_cnt)
			goto count;

		hdr = genlmsg_put(skb, portid, cb->nlh->nlmsg_seq,
				  &tipc_genl_family, NLM_F_MULTI,
				  TIPC_NL_BEARER_GET);
		if (!hdr)
			goto done;

		err = __tipc_nl_add_udp_addr(skb, &rcast->addr,
					     TIPC_NLA_UDP_REMOTE);
		if (err) {
			genlmsg_cancel(skb, hdr);
			goto done;
		}
		genlmsg_end(skb, hdr);
count:
		i++;
	}
done:
	rtnl_unlock();
	cb->args[0] = bid;
	cb->args[1] = i;

	return skb->len;
}

541 542 543 544 545 546 547
int tipc_udp_nl_add_bearer_data(struct tipc_nl_msg *msg, struct tipc_bearer *b)
{
	struct udp_media_addr *src = (struct udp_media_addr *)&b->addr.value;
	struct udp_media_addr *dst;
	struct udp_bearer *ub;
	struct nlattr *nest;

548
	ub = rtnl_dereference(b->media_ptr);
549 550 551
	if (!ub)
		return -ENODEV;

552
	nest = nla_nest_start_noflag(msg->skb, TIPC_NLA_BEARER_UDP_OPTS);
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574
	if (!nest)
		goto msg_full;

	if (__tipc_nl_add_udp_addr(msg->skb, src, TIPC_NLA_UDP_LOCAL))
		goto msg_full;

	dst = (struct udp_media_addr *)&b->bcast_addr.value;
	if (__tipc_nl_add_udp_addr(msg->skb, dst, TIPC_NLA_UDP_REMOTE))
		goto msg_full;

	if (!list_empty(&ub->rcast.list)) {
		if (nla_put_flag(msg->skb, TIPC_NLA_UDP_MULTI_REMOTEIP))
			goto msg_full;
	}

	nla_nest_end(msg->skb, nest);
	return 0;
msg_full:
	nla_nest_cancel(msg->skb, nest);
	return -EMSGSIZE;
}

E
Erik Hugne 已提交
575
/**
576
 * tipc_parse_udp_addr - build udp media address from netlink data
A
Andrew Lunn 已提交
577
 * @nla:	netlink attribute containing sockaddr storage aligned address
578 579
 * @addr:	tipc media address to fill with address, port and protocol type
 * @scope_id:	IPv6 scope id pointer, not NULL indicates it's required
E
Erik Hugne 已提交
580
 */
581 582 583

static int tipc_parse_udp_addr(struct nlattr *nla, struct udp_media_addr *addr,
			       u32 *scope_id)
E
Erik Hugne 已提交
584
{
585
	struct sockaddr_storage sa;
E
Erik Hugne 已提交
586

587 588 589 590 591 592 593
	nla_memcpy(&sa, nla, sizeof(sa));
	if (sa.ss_family == AF_INET) {
		struct sockaddr_in *ip4 = (struct sockaddr_in *)&sa;

		addr->proto = htons(ETH_P_IP);
		addr->port = ip4->sin_port;
		addr->ipv4.s_addr = ip4->sin_addr.s_addr;
E
Erik Hugne 已提交
594 595 596
		return 0;

#if IS_ENABLED(CONFIG_IPV6)
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
	} else if (sa.ss_family == AF_INET6) {
		struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)&sa;

		addr->proto = htons(ETH_P_IPV6);
		addr->port = ip6->sin6_port;
		memcpy(&addr->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr));

		/* Scope ID is only interesting for local addresses */
		if (scope_id) {
			int atype;

			atype = ipv6_addr_type(&ip6->sin6_addr);
			if (__ipv6_addr_needs_scope_id(atype) &&
			    !ip6->sin6_scope_id) {
				return -EINVAL;
			}

			*scope_id = ip6->sin6_scope_id ? : 0;
		}

E
Erik Hugne 已提交
617 618 619 620 621 622
		return 0;
#endif
	}
	return -EADDRNOTAVAIL;
}

R
Richard Alpe 已提交
623 624 625 626 627 628 629
int tipc_udp_nl_bearer_add(struct tipc_bearer *b, struct nlattr *attr)
{
	int err;
	struct udp_media_addr addr = {0};
	struct nlattr *opts[TIPC_NLA_UDP_MAX + 1];
	struct udp_media_addr *dst;

630
	if (nla_parse_nested_deprecated(opts, TIPC_NLA_UDP_MAX, attr, tipc_nl_udp_policy, NULL))
R
Richard Alpe 已提交
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645
		return -EINVAL;

	if (!opts[TIPC_NLA_UDP_REMOTE])
		return -EINVAL;

	err = tipc_parse_udp_addr(opts[TIPC_NLA_UDP_REMOTE], &addr, NULL);
	if (err)
		return err;

	dst = (struct udp_media_addr *)&b->bcast_addr.value;
	if (tipc_udp_is_mcast_addr(dst)) {
		pr_err("Can't add remote ip to TIPC UDP multicast bearer\n");
		return -EINVAL;
	}

646 647 648
	if (tipc_udp_is_known_peer(b, &addr))
		return 0;

R
Richard Alpe 已提交
649 650 651
	return tipc_udp_rcast_add(b, &addr);
}

E
Erik Hugne 已提交
652 653 654 655 656 657 658 659 660 661 662 663 664 665
/**
 * tipc_udp_enable - callback to create a new udp bearer instance
 * @net:	network namespace
 * @b:		pointer to generic tipc_bearer
 * @attrs:	netlink bearer configuration
 *
 * validate the bearer parameters and initialize the udp bearer
 * rtnl_lock should be held
 */
static int tipc_udp_enable(struct net *net, struct tipc_bearer *b,
			   struct nlattr *attrs[])
{
	int err = -EINVAL;
	struct udp_bearer *ub;
R
Richard Alpe 已提交
666
	struct udp_media_addr remote = {0};
E
Erik Hugne 已提交
667 668
	struct udp_media_addr local = {0};
	struct udp_port_cfg udp_conf = {0};
669
	struct udp_tunnel_sock_cfg tuncfg = {NULL};
670
	struct nlattr *opts[TIPC_NLA_UDP_MAX + 1];
671
	u8 node_id[NODE_ID_LEN] = {0,};
X
Xin Long 已提交
672
	struct net_device *dev;
673
	int rmcast = 0;
E
Erik Hugne 已提交
674 675 676 677 678

	ub = kzalloc(sizeof(*ub), GFP_ATOMIC);
	if (!ub)
		return -ENOMEM;

R
Richard Alpe 已提交
679 680
	INIT_LIST_HEAD(&ub->rcast.list);

681 682 683
	if (!attrs[TIPC_NLA_BEARER_UDP_OPTS])
		goto err;

684
	if (nla_parse_nested_deprecated(opts, TIPC_NLA_UDP_MAX, attrs[TIPC_NLA_BEARER_UDP_OPTS], tipc_nl_udp_policy, NULL))
685 686 687 688
		goto err;

	if (!opts[TIPC_NLA_UDP_LOCAL] || !opts[TIPC_NLA_UDP_REMOTE]) {
		pr_err("Invalid UDP bearer configuration");
689 690
		err = -EINVAL;
		goto err;
691 692 693 694 695 696 697
	}

	err = tipc_parse_udp_addr(opts[TIPC_NLA_UDP_LOCAL], &local,
				  &ub->ifindex);
	if (err)
		goto err;

R
Richard Alpe 已提交
698
	err = tipc_parse_udp_addr(opts[TIPC_NLA_UDP_REMOTE], &remote, NULL);
E
Erik Hugne 已提交
699 700 701
	if (err)
		goto err;

702 703 704 705 706
	if (remote.proto != local.proto) {
		err = -EINVAL;
		goto err;
	}

707 708 709
	/* Checking remote ip address */
	rmcast = tipc_udp_is_mcast_addr(&remote);

710 711 712 713 714 715 716
	/* Autoconfigure own node identity if needed */
	if (!tipc_own_id(net)) {
		memcpy(node_id, local.ipv6.in6_u.u6_addr8, 16);
		tipc_net_init(net, node_id, 0);
	}
	if (!tipc_own_id(net)) {
		pr_warn("Failed to set node id, please configure manually\n");
717 718
		err = -EINVAL;
		goto err;
719 720
	}

E
Erik Hugne 已提交
721
	b->bcast_addr.media_id = TIPC_MEDIA_TYPE_UDP;
722
	b->bcast_addr.broadcast = TIPC_BROADCAST_SUPPORT;
E
Erik Hugne 已提交
723 724 725
	rcu_assign_pointer(b->media_ptr, ub);
	rcu_assign_pointer(ub->bearer, b);
	tipc_udp_media_addr_set(&b->addr, &local);
726
	if (local.proto == htons(ETH_P_IP)) {
E
Erik Hugne 已提交
727 728 729 730 731 732
		dev = __ip_dev_find(net, local.ipv4.s_addr, false);
		if (!dev) {
			err = -ENODEV;
			goto err;
		}
		udp_conf.family = AF_INET;
733 734 735 736 737 738

		/* Switch to use ANY to receive packets from group */
		if (rmcast)
			udp_conf.local_ip.s_addr = htonl(INADDR_ANY);
		else
			udp_conf.local_ip.s_addr = local.ipv4.s_addr;
E
Erik Hugne 已提交
739 740
		udp_conf.use_udp_checksums = false;
		ub->ifindex = dev->ifindex;
741 742
		b->encap_hlen = sizeof(struct iphdr) + sizeof(struct udphdr);
		if (tipc_mtu_bad(dev, b->encap_hlen)) {
M
Michal Kubeček 已提交
743 744 745
			err = -EINVAL;
			goto err;
		}
746
		b->mtu = b->media->mtu;
E
Erik Hugne 已提交
747
#if IS_ENABLED(CONFIG_IPV6)
748
	} else if (local.proto == htons(ETH_P_IPV6)) {
X
Xin Long 已提交
749 750
		dev = ub->ifindex ? __dev_get_by_index(net, ub->ifindex) : NULL;
		dev = ipv6_dev_find(net, &local.ipv6, dev);
751 752 753 754
		if (!dev) {
			err = -ENODEV;
			goto err;
		}
E
Erik Hugne 已提交
755 756 757
		udp_conf.family = AF_INET6;
		udp_conf.use_udp6_tx_checksums = true;
		udp_conf.use_udp6_rx_checksums = true;
758 759 760 761
		if (rmcast)
			udp_conf.local_ip6 = in6addr_any;
		else
			udp_conf.local_ip6 = local.ipv6;
762
		ub->ifindex = dev->ifindex;
763
		b->encap_hlen = sizeof(struct ipv6hdr) + sizeof(struct udphdr);
E
Erik Hugne 已提交
764 765 766 767 768 769
		b->mtu = 1280;
#endif
	} else {
		err = -EAFNOSUPPORT;
		goto err;
	}
770
	udp_conf.local_udp_port = local.port;
E
Erik Hugne 已提交
771 772 773 774 775 776 777 778 779
	err = udp_sock_create(net, &udp_conf, &ub->ubsock);
	if (err)
		goto err;
	tuncfg.sk_user_data = ub;
	tuncfg.encap_type = 1;
	tuncfg.encap_rcv = tipc_udp_recv;
	tuncfg.encap_destroy = NULL;
	setup_udp_tunnel_sock(net, ub->ubsock, &tuncfg);

780 781
	err = dst_cache_init(&ub->rcast.dst_cache, GFP_ATOMIC);
	if (err)
X
Xin Long 已提交
782
		goto free;
783

784
	/*
R
Richard Alpe 已提交
785 786 787 788
	 * The bcast media address port is used for all peers and the ip
	 * is used if it's a multicast address.
	 */
	memcpy(&b->bcast_addr.value, &remote, sizeof(remote));
789
	if (rmcast)
R
Richard Alpe 已提交
790 791 792 793
		err = enable_mcast(ub, &remote);
	else
		err = tipc_udp_rcast_add(b, &remote);
	if (err)
X
Xin Long 已提交
794
		goto free;
R
Richard Alpe 已提交
795

E
Erik Hugne 已提交
796
	return 0;
X
Xin Long 已提交
797 798

free:
799
	dst_cache_destroy(&ub->rcast.dst_cache);
X
Xin Long 已提交
800 801
	udp_tunnel_sock_release(ub->ubsock);
err:
E
Erik Hugne 已提交
802 803 804 805 806 807 808 809
	kfree(ub);
	return err;
}

/* cleanup_bearer - break the socket/bearer association */
static void cleanup_bearer(struct work_struct *work)
{
	struct udp_bearer *ub = container_of(work, struct udp_bearer, work);
R
Richard Alpe 已提交
810 811 812
	struct udp_replicast *rcast, *tmp;

	list_for_each_entry_safe(rcast, tmp, &ub->rcast.list, list) {
813
		dst_cache_destroy(&rcast->dst_cache);
R
Richard Alpe 已提交
814 815 816
		list_del_rcu(&rcast->list);
		kfree_rcu(rcast, rcu);
	}
E
Erik Hugne 已提交
817

818
	atomic_dec(&tipc_net(sock_net(ub->ubsock->sk))->wq_count);
819
	dst_cache_destroy(&ub->rcast.dst_cache);
X
Xin Long 已提交
820
	udp_tunnel_sock_release(ub->ubsock);
E
Erik Hugne 已提交
821 822 823 824 825 826 827 828 829
	synchronize_net();
	kfree(ub);
}

/* tipc_udp_disable - detach bearer from socket */
static void tipc_udp_disable(struct tipc_bearer *b)
{
	struct udp_bearer *ub;

830
	ub = rtnl_dereference(b->media_ptr);
E
Erik Hugne 已提交
831 832 833 834
	if (!ub) {
		pr_err("UDP bearer instance not found\n");
		return;
	}
X
Xin Long 已提交
835
	sock_set_flag(ub->ubsock->sk, SOCK_DEAD);
E
Erik Hugne 已提交
836 837 838
	RCU_INIT_POINTER(ub->bearer, NULL);

	/* sock_release need to be done outside of rtnl lock */
839
	atomic_inc(&tipc_net(sock_net(ub->ubsock->sk))->wq_count);
E
Erik Hugne 已提交
840 841 842 843 844 845 846 847 848 849 850 851 852
	INIT_WORK(&ub->work, cleanup_bearer);
	schedule_work(&ub->work);
}

struct tipc_media udp_media_info = {
	.send_msg	= tipc_udp_send_msg,
	.enable_media	= tipc_udp_enable,
	.disable_media	= tipc_udp_disable,
	.addr2str	= tipc_udp_addr2str,
	.addr2msg	= tipc_udp_addr2msg,
	.msg2addr	= tipc_udp_msg2addr,
	.priority	= TIPC_DEF_LINK_PRI,
	.tolerance	= TIPC_DEF_LINK_TOL,
853 854
	.min_win	= TIPC_DEF_LINK_WIN,
	.max_win	= TIPC_DEF_LINK_WIN,
855
	.mtu		= TIPC_DEF_LINK_UDP_MTU,
E
Erik Hugne 已提交
856 857 858 859
	.type_id	= TIPC_MEDIA_TYPE_UDP,
	.hwaddr_len	= 0,
	.name		= "udp"
};