3449 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/* Copyright (c) 2021 Taehee Yoo <ap420073@gmail.com> */3 4#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt5 6#include <linux/module.h>7#include <linux/skbuff.h>8#include <linux/udp.h>9#include <linux/jhash.h>10#include <linux/if_tunnel.h>11#include <linux/net.h>12#include <linux/igmp.h>13#include <linux/workqueue.h>14#include <net/pkt_sched.h>15#include <net/net_namespace.h>16#include <net/ip.h>17#include <net/udp.h>18#include <net/udp_tunnel.h>19#include <net/icmp.h>20#include <net/mld.h>21#include <net/amt.h>22#include <uapi/linux/amt.h>23#include <linux/security.h>24#include <net/gro_cells.h>25#include <net/ipv6.h>26#include <net/if_inet6.h>27#include <net/ndisc.h>28#include <net/addrconf.h>29#include <net/ip6_route.h>30#include <net/inet_common.h>31#include <net/ip6_checksum.h>32 33static struct workqueue_struct *amt_wq;34 35static HLIST_HEAD(source_gc_list);36/* Lock for source_gc_list */37static spinlock_t source_gc_lock;38static struct delayed_work source_gc_wq;39static char *status_str[] = {40 "AMT_STATUS_INIT",41 "AMT_STATUS_SENT_DISCOVERY",42 "AMT_STATUS_RECEIVED_DISCOVERY",43 "AMT_STATUS_SENT_ADVERTISEMENT",44 "AMT_STATUS_RECEIVED_ADVERTISEMENT",45 "AMT_STATUS_SENT_REQUEST",46 "AMT_STATUS_RECEIVED_REQUEST",47 "AMT_STATUS_SENT_QUERY",48 "AMT_STATUS_RECEIVED_QUERY",49 "AMT_STATUS_SENT_UPDATE",50 "AMT_STATUS_RECEIVED_UPDATE",51};52 53static char *type_str[] = {54 "", /* Type 0 is not defined */55 "AMT_MSG_DISCOVERY",56 "AMT_MSG_ADVERTISEMENT",57 "AMT_MSG_REQUEST",58 "AMT_MSG_MEMBERSHIP_QUERY",59 "AMT_MSG_MEMBERSHIP_UPDATE",60 "AMT_MSG_MULTICAST_DATA",61 "AMT_MSG_TEARDOWN",62};63 64static char *action_str[] = {65 "AMT_ACT_GMI",66 "AMT_ACT_GMI_ZERO",67 "AMT_ACT_GT",68 "AMT_ACT_STATUS_FWD_NEW",69 "AMT_ACT_STATUS_D_FWD_NEW",70 "AMT_ACT_STATUS_NONE_NEW",71};72 73static struct igmpv3_grec igmpv3_zero_grec;74 75#if IS_ENABLED(CONFIG_IPV6)76#define MLD2_ALL_NODE_INIT { { { 0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } }77static struct in6_addr mld2_all_node = MLD2_ALL_NODE_INIT;78static struct mld2_grec mldv2_zero_grec;79#endif80 81static struct amt_skb_cb *amt_skb_cb(struct sk_buff *skb)82{83 BUILD_BUG_ON(sizeof(struct amt_skb_cb) + sizeof(struct tc_skb_cb) >84 sizeof_field(struct sk_buff, cb));85 86 return (struct amt_skb_cb *)((void *)skb->cb +87 sizeof(struct tc_skb_cb));88}89 90static void __amt_source_gc_work(void)91{92 struct amt_source_node *snode;93 struct hlist_head gc_list;94 struct hlist_node *t;95 96 spin_lock_bh(&source_gc_lock);97 hlist_move_list(&source_gc_list, &gc_list);98 spin_unlock_bh(&source_gc_lock);99 100 hlist_for_each_entry_safe(snode, t, &gc_list, node) {101 hlist_del_rcu(&snode->node);102 kfree_rcu(snode, rcu);103 }104}105 106static void amt_source_gc_work(struct work_struct *work)107{108 __amt_source_gc_work();109 110 spin_lock_bh(&source_gc_lock);111 mod_delayed_work(amt_wq, &source_gc_wq,112 msecs_to_jiffies(AMT_GC_INTERVAL));113 spin_unlock_bh(&source_gc_lock);114}115 116static bool amt_addr_equal(union amt_addr *a, union amt_addr *b)117{118 return !memcmp(a, b, sizeof(union amt_addr));119}120 121static u32 amt_source_hash(struct amt_tunnel_list *tunnel, union amt_addr *src)122{123 u32 hash = jhash(src, sizeof(*src), tunnel->amt->hash_seed);124 125 return reciprocal_scale(hash, tunnel->amt->hash_buckets);126}127 128static bool amt_status_filter(struct amt_source_node *snode,129 enum amt_filter filter)130{131 bool rc = false;132 133 switch (filter) {134 case AMT_FILTER_FWD:135 if (snode->status == AMT_SOURCE_STATUS_FWD &&136 snode->flags == AMT_SOURCE_OLD)137 rc = true;138 break;139 case AMT_FILTER_D_FWD:140 if (snode->status == AMT_SOURCE_STATUS_D_FWD &&141 snode->flags == AMT_SOURCE_OLD)142 rc = true;143 break;144 case AMT_FILTER_FWD_NEW:145 if (snode->status == AMT_SOURCE_STATUS_FWD &&146 snode->flags == AMT_SOURCE_NEW)147 rc = true;148 break;149 case AMT_FILTER_D_FWD_NEW:150 if (snode->status == AMT_SOURCE_STATUS_D_FWD &&151 snode->flags == AMT_SOURCE_NEW)152 rc = true;153 break;154 case AMT_FILTER_ALL:155 rc = true;156 break;157 case AMT_FILTER_NONE_NEW:158 if (snode->status == AMT_SOURCE_STATUS_NONE &&159 snode->flags == AMT_SOURCE_NEW)160 rc = true;161 break;162 case AMT_FILTER_BOTH:163 if ((snode->status == AMT_SOURCE_STATUS_D_FWD ||164 snode->status == AMT_SOURCE_STATUS_FWD) &&165 snode->flags == AMT_SOURCE_OLD)166 rc = true;167 break;168 case AMT_FILTER_BOTH_NEW:169 if ((snode->status == AMT_SOURCE_STATUS_D_FWD ||170 snode->status == AMT_SOURCE_STATUS_FWD) &&171 snode->flags == AMT_SOURCE_NEW)172 rc = true;173 break;174 default:175 WARN_ON_ONCE(1);176 break;177 }178 179 return rc;180}181 182static struct amt_source_node *amt_lookup_src(struct amt_tunnel_list *tunnel,183 struct amt_group_node *gnode,184 enum amt_filter filter,185 union amt_addr *src)186{187 u32 hash = amt_source_hash(tunnel, src);188 struct amt_source_node *snode;189 190 hlist_for_each_entry_rcu(snode, &gnode->sources[hash], node)191 if (amt_status_filter(snode, filter) &&192 amt_addr_equal(&snode->source_addr, src))193 return snode;194 195 return NULL;196}197 198static u32 amt_group_hash(struct amt_tunnel_list *tunnel, union amt_addr *group)199{200 u32 hash = jhash(group, sizeof(*group), tunnel->amt->hash_seed);201 202 return reciprocal_scale(hash, tunnel->amt->hash_buckets);203}204 205static struct amt_group_node *amt_lookup_group(struct amt_tunnel_list *tunnel,206 union amt_addr *group,207 union amt_addr *host,208 bool v6)209{210 u32 hash = amt_group_hash(tunnel, group);211 struct amt_group_node *gnode;212 213 hlist_for_each_entry_rcu(gnode, &tunnel->groups[hash], node) {214 if (amt_addr_equal(&gnode->group_addr, group) &&215 amt_addr_equal(&gnode->host_addr, host) &&216 gnode->v6 == v6)217 return gnode;218 }219 220 return NULL;221}222 223static void amt_destroy_source(struct amt_source_node *snode)224{225 struct amt_group_node *gnode = snode->gnode;226 struct amt_tunnel_list *tunnel;227 228 tunnel = gnode->tunnel_list;229 230 if (!gnode->v6) {231 netdev_dbg(snode->gnode->amt->dev,232 "Delete source %pI4 from %pI4\n",233 &snode->source_addr.ip4,234 &gnode->group_addr.ip4);235#if IS_ENABLED(CONFIG_IPV6)236 } else {237 netdev_dbg(snode->gnode->amt->dev,238 "Delete source %pI6 from %pI6\n",239 &snode->source_addr.ip6,240 &gnode->group_addr.ip6);241#endif242 }243 244 cancel_delayed_work(&snode->source_timer);245 hlist_del_init_rcu(&snode->node);246 tunnel->nr_sources--;247 gnode->nr_sources--;248 spin_lock_bh(&source_gc_lock);249 hlist_add_head_rcu(&snode->node, &source_gc_list);250 spin_unlock_bh(&source_gc_lock);251}252 253static void amt_del_group(struct amt_dev *amt, struct amt_group_node *gnode)254{255 struct amt_source_node *snode;256 struct hlist_node *t;257 int i;258 259 if (cancel_delayed_work(&gnode->group_timer))260 dev_put(amt->dev);261 hlist_del_rcu(&gnode->node);262 gnode->tunnel_list->nr_groups--;263 264 if (!gnode->v6)265 netdev_dbg(amt->dev, "Leave group %pI4\n",266 &gnode->group_addr.ip4);267#if IS_ENABLED(CONFIG_IPV6)268 else269 netdev_dbg(amt->dev, "Leave group %pI6\n",270 &gnode->group_addr.ip6);271#endif272 for (i = 0; i < amt->hash_buckets; i++)273 hlist_for_each_entry_safe(snode, t, &gnode->sources[i], node)274 amt_destroy_source(snode);275 276 /* tunnel->lock was acquired outside of amt_del_group()277 * But rcu_read_lock() was acquired too so It's safe.278 */279 kfree_rcu(gnode, rcu);280}281 282/* If a source timer expires with a router filter-mode for the group of283 * INCLUDE, the router concludes that traffic from this particular284 * source is no longer desired on the attached network, and deletes the285 * associated source record.286 */287static void amt_source_work(struct work_struct *work)288{289 struct amt_source_node *snode = container_of(to_delayed_work(work),290 struct amt_source_node,291 source_timer);292 struct amt_group_node *gnode = snode->gnode;293 struct amt_dev *amt = gnode->amt;294 struct amt_tunnel_list *tunnel;295 296 tunnel = gnode->tunnel_list;297 spin_lock_bh(&tunnel->lock);298 rcu_read_lock();299 if (gnode->filter_mode == MCAST_INCLUDE) {300 amt_destroy_source(snode);301 if (!gnode->nr_sources)302 amt_del_group(amt, gnode);303 } else {304 /* When a router filter-mode for a group is EXCLUDE,305 * source records are only deleted when the group timer expires306 */307 snode->status = AMT_SOURCE_STATUS_D_FWD;308 }309 rcu_read_unlock();310 spin_unlock_bh(&tunnel->lock);311}312 313static void amt_act_src(struct amt_tunnel_list *tunnel,314 struct amt_group_node *gnode,315 struct amt_source_node *snode,316 enum amt_act act)317{318 struct amt_dev *amt = tunnel->amt;319 320 switch (act) {321 case AMT_ACT_GMI:322 mod_delayed_work(amt_wq, &snode->source_timer,323 msecs_to_jiffies(amt_gmi(amt)));324 break;325 case AMT_ACT_GMI_ZERO:326 cancel_delayed_work(&snode->source_timer);327 break;328 case AMT_ACT_GT:329 mod_delayed_work(amt_wq, &snode->source_timer,330 gnode->group_timer.timer.expires);331 break;332 case AMT_ACT_STATUS_FWD_NEW:333 snode->status = AMT_SOURCE_STATUS_FWD;334 snode->flags = AMT_SOURCE_NEW;335 break;336 case AMT_ACT_STATUS_D_FWD_NEW:337 snode->status = AMT_SOURCE_STATUS_D_FWD;338 snode->flags = AMT_SOURCE_NEW;339 break;340 case AMT_ACT_STATUS_NONE_NEW:341 cancel_delayed_work(&snode->source_timer);342 snode->status = AMT_SOURCE_STATUS_NONE;343 snode->flags = AMT_SOURCE_NEW;344 break;345 default:346 WARN_ON_ONCE(1);347 return;348 }349 350 if (!gnode->v6)351 netdev_dbg(amt->dev, "Source %pI4 from %pI4 Acted %s\n",352 &snode->source_addr.ip4,353 &gnode->group_addr.ip4,354 action_str[act]);355#if IS_ENABLED(CONFIG_IPV6)356 else357 netdev_dbg(amt->dev, "Source %pI6 from %pI6 Acted %s\n",358 &snode->source_addr.ip6,359 &gnode->group_addr.ip6,360 action_str[act]);361#endif362}363 364static struct amt_source_node *amt_alloc_snode(struct amt_group_node *gnode,365 union amt_addr *src)366{367 struct amt_source_node *snode;368 369 snode = kzalloc(sizeof(*snode), GFP_ATOMIC);370 if (!snode)371 return NULL;372 373 memcpy(&snode->source_addr, src, sizeof(union amt_addr));374 snode->gnode = gnode;375 snode->status = AMT_SOURCE_STATUS_NONE;376 snode->flags = AMT_SOURCE_NEW;377 INIT_HLIST_NODE(&snode->node);378 INIT_DELAYED_WORK(&snode->source_timer, amt_source_work);379 380 return snode;381}382 383/* RFC 3810 - 7.2.2. Definition of Filter Timers384 *385 * Router Mode Filter Timer Actions/Comments386 * ----------- ----------------- ----------------387 *388 * INCLUDE Not Used All listeners in389 * INCLUDE mode.390 *391 * EXCLUDE Timer > 0 At least one listener392 * in EXCLUDE mode.393 *394 * EXCLUDE Timer == 0 No more listeners in395 * EXCLUDE mode for the396 * multicast address.397 * If the Requested List398 * is empty, delete399 * Multicast Address400 * Record. If not, switch401 * to INCLUDE filter mode;402 * the sources in the403 * Requested List are404 * moved to the Include405 * List, and the Exclude406 * List is deleted.407 */408static void amt_group_work(struct work_struct *work)409{410 struct amt_group_node *gnode = container_of(to_delayed_work(work),411 struct amt_group_node,412 group_timer);413 struct amt_tunnel_list *tunnel = gnode->tunnel_list;414 struct amt_dev *amt = gnode->amt;415 struct amt_source_node *snode;416 bool delete_group = true;417 struct hlist_node *t;418 int i, buckets;419 420 buckets = amt->hash_buckets;421 422 spin_lock_bh(&tunnel->lock);423 if (gnode->filter_mode == MCAST_INCLUDE) {424 /* Not Used */425 spin_unlock_bh(&tunnel->lock);426 goto out;427 }428 429 rcu_read_lock();430 for (i = 0; i < buckets; i++) {431 hlist_for_each_entry_safe(snode, t,432 &gnode->sources[i], node) {433 if (!delayed_work_pending(&snode->source_timer) ||434 snode->status == AMT_SOURCE_STATUS_D_FWD) {435 amt_destroy_source(snode);436 } else {437 delete_group = false;438 snode->status = AMT_SOURCE_STATUS_FWD;439 }440 }441 }442 if (delete_group)443 amt_del_group(amt, gnode);444 else445 gnode->filter_mode = MCAST_INCLUDE;446 rcu_read_unlock();447 spin_unlock_bh(&tunnel->lock);448out:449 dev_put(amt->dev);450}451 452/* Non-existent group is created as INCLUDE {empty}:453 *454 * RFC 3376 - 5.1. Action on Change of Interface State455 *456 * If no interface state existed for that multicast address before457 * the change (i.e., the change consisted of creating a new458 * per-interface record), or if no state exists after the change459 * (i.e., the change consisted of deleting a per-interface record),460 * then the "non-existent" state is considered to have a filter mode461 * of INCLUDE and an empty source list.462 */463static struct amt_group_node *amt_add_group(struct amt_dev *amt,464 struct amt_tunnel_list *tunnel,465 union amt_addr *group,466 union amt_addr *host,467 bool v6)468{469 struct amt_group_node *gnode;470 u32 hash;471 int i;472 473 if (tunnel->nr_groups >= amt->max_groups)474 return ERR_PTR(-ENOSPC);475 476 gnode = kzalloc(sizeof(*gnode) +477 (sizeof(struct hlist_head) * amt->hash_buckets),478 GFP_ATOMIC);479 if (unlikely(!gnode))480 return ERR_PTR(-ENOMEM);481 482 gnode->amt = amt;483 gnode->group_addr = *group;484 gnode->host_addr = *host;485 gnode->v6 = v6;486 gnode->tunnel_list = tunnel;487 gnode->filter_mode = MCAST_INCLUDE;488 INIT_HLIST_NODE(&gnode->node);489 INIT_DELAYED_WORK(&gnode->group_timer, amt_group_work);490 for (i = 0; i < amt->hash_buckets; i++)491 INIT_HLIST_HEAD(&gnode->sources[i]);492 493 hash = amt_group_hash(tunnel, group);494 hlist_add_head_rcu(&gnode->node, &tunnel->groups[hash]);495 tunnel->nr_groups++;496 497 if (!gnode->v6)498 netdev_dbg(amt->dev, "Join group %pI4\n",499 &gnode->group_addr.ip4);500#if IS_ENABLED(CONFIG_IPV6)501 else502 netdev_dbg(amt->dev, "Join group %pI6\n",503 &gnode->group_addr.ip6);504#endif505 506 return gnode;507}508 509static struct sk_buff *amt_build_igmp_gq(struct amt_dev *amt)510{511 u8 ra[AMT_IPHDR_OPTS] = { IPOPT_RA, 4, 0, 0 };512 int hlen = LL_RESERVED_SPACE(amt->dev);513 int tlen = amt->dev->needed_tailroom;514 struct igmpv3_query *ihv3;515 void *csum_start = NULL;516 __sum16 *csum = NULL;517 struct sk_buff *skb;518 struct ethhdr *eth;519 struct iphdr *iph;520 unsigned int len;521 int offset;522 523 len = hlen + tlen + sizeof(*iph) + AMT_IPHDR_OPTS + sizeof(*ihv3);524 skb = netdev_alloc_skb_ip_align(amt->dev, len);525 if (!skb)526 return NULL;527 528 skb_reserve(skb, hlen);529 skb_push(skb, sizeof(*eth));530 skb->protocol = htons(ETH_P_IP);531 skb_reset_mac_header(skb);532 skb->priority = TC_PRIO_CONTROL;533 skb_put(skb, sizeof(*iph));534 skb_put_data(skb, ra, sizeof(ra));535 skb_put(skb, sizeof(*ihv3));536 skb_pull(skb, sizeof(*eth));537 skb_reset_network_header(skb);538 539 iph = ip_hdr(skb);540 iph->version = 4;541 iph->ihl = (sizeof(struct iphdr) + AMT_IPHDR_OPTS) >> 2;542 iph->tos = AMT_TOS;543 iph->tot_len = htons(sizeof(*iph) + AMT_IPHDR_OPTS + sizeof(*ihv3));544 iph->frag_off = htons(IP_DF);545 iph->ttl = 1;546 iph->id = 0;547 iph->protocol = IPPROTO_IGMP;548 iph->daddr = htonl(INADDR_ALLHOSTS_GROUP);549 iph->saddr = htonl(INADDR_ANY);550 ip_send_check(iph);551 552 eth = eth_hdr(skb);553 ether_addr_copy(eth->h_source, amt->dev->dev_addr);554 ip_eth_mc_map(htonl(INADDR_ALLHOSTS_GROUP), eth->h_dest);555 eth->h_proto = htons(ETH_P_IP);556 557 ihv3 = skb_pull(skb, sizeof(*iph) + AMT_IPHDR_OPTS);558 skb_reset_transport_header(skb);559 ihv3->type = IGMP_HOST_MEMBERSHIP_QUERY;560 ihv3->code = 1;561 ihv3->group = 0;562 ihv3->qqic = amt->qi;563 ihv3->nsrcs = 0;564 ihv3->resv = 0;565 ihv3->suppress = false;566 ihv3->qrv = READ_ONCE(amt->net->ipv4.sysctl_igmp_qrv);567 ihv3->csum = 0;568 csum = &ihv3->csum;569 csum_start = (void *)ihv3;570 *csum = ip_compute_csum(csum_start, sizeof(*ihv3));571 offset = skb_transport_offset(skb);572 skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);573 skb->ip_summed = CHECKSUM_NONE;574 575 skb_push(skb, sizeof(*eth) + sizeof(*iph) + AMT_IPHDR_OPTS);576 577 return skb;578}579 580static void amt_update_gw_status(struct amt_dev *amt, enum amt_status status,581 bool validate)582{583 if (validate && amt->status >= status)584 return;585 netdev_dbg(amt->dev, "Update GW status %s -> %s",586 status_str[amt->status], status_str[status]);587 WRITE_ONCE(amt->status, status);588}589 590static void __amt_update_relay_status(struct amt_tunnel_list *tunnel,591 enum amt_status status,592 bool validate)593{594 if (validate && tunnel->status >= status)595 return;596 netdev_dbg(tunnel->amt->dev,597 "Update Tunnel(IP = %pI4, PORT = %u) status %s -> %s",598 &tunnel->ip4, ntohs(tunnel->source_port),599 status_str[tunnel->status], status_str[status]);600 tunnel->status = status;601}602 603static void amt_update_relay_status(struct amt_tunnel_list *tunnel,604 enum amt_status status, bool validate)605{606 spin_lock_bh(&tunnel->lock);607 __amt_update_relay_status(tunnel, status, validate);608 spin_unlock_bh(&tunnel->lock);609}610 611static void amt_send_discovery(struct amt_dev *amt)612{613 struct amt_header_discovery *amtd;614 int hlen, tlen, offset;615 struct socket *sock;616 struct udphdr *udph;617 struct sk_buff *skb;618 struct iphdr *iph;619 struct rtable *rt;620 struct flowi4 fl4;621 u32 len;622 int err;623 624 rcu_read_lock();625 sock = rcu_dereference(amt->sock);626 if (!sock)627 goto out;628 629 if (!netif_running(amt->stream_dev) || !netif_running(amt->dev))630 goto out;631 632 rt = ip_route_output_ports(amt->net, &fl4, sock->sk,633 amt->discovery_ip, amt->local_ip,634 amt->gw_port, amt->relay_port,635 IPPROTO_UDP, 0,636 amt->stream_dev->ifindex);637 if (IS_ERR(rt)) {638 amt->dev->stats.tx_errors++;639 goto out;640 }641 642 hlen = LL_RESERVED_SPACE(amt->dev);643 tlen = amt->dev->needed_tailroom;644 len = hlen + tlen + sizeof(*iph) + sizeof(*udph) + sizeof(*amtd);645 skb = netdev_alloc_skb_ip_align(amt->dev, len);646 if (!skb) {647 ip_rt_put(rt);648 amt->dev->stats.tx_errors++;649 goto out;650 }651 652 skb->priority = TC_PRIO_CONTROL;653 skb_dst_set(skb, &rt->dst);654 655 len = sizeof(*iph) + sizeof(*udph) + sizeof(*amtd);656 skb_reset_network_header(skb);657 skb_put(skb, len);658 amtd = skb_pull(skb, sizeof(*iph) + sizeof(*udph));659 amtd->version = 0;660 amtd->type = AMT_MSG_DISCOVERY;661 amtd->reserved = 0;662 amtd->nonce = amt->nonce;663 skb_push(skb, sizeof(*udph));664 skb_reset_transport_header(skb);665 udph = udp_hdr(skb);666 udph->source = amt->gw_port;667 udph->dest = amt->relay_port;668 udph->len = htons(sizeof(*udph) + sizeof(*amtd));669 udph->check = 0;670 offset = skb_transport_offset(skb);671 skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);672 udph->check = csum_tcpudp_magic(amt->local_ip, amt->discovery_ip,673 sizeof(*udph) + sizeof(*amtd),674 IPPROTO_UDP, skb->csum);675 676 skb_push(skb, sizeof(*iph));677 iph = ip_hdr(skb);678 iph->version = 4;679 iph->ihl = (sizeof(struct iphdr)) >> 2;680 iph->tos = AMT_TOS;681 iph->frag_off = 0;682 iph->ttl = ip4_dst_hoplimit(&rt->dst);683 iph->daddr = amt->discovery_ip;684 iph->saddr = amt->local_ip;685 iph->protocol = IPPROTO_UDP;686 iph->tot_len = htons(len);687 688 skb->ip_summed = CHECKSUM_NONE;689 ip_select_ident(amt->net, skb, NULL);690 ip_send_check(iph);691 err = ip_local_out(amt->net, sock->sk, skb);692 if (unlikely(net_xmit_eval(err)))693 amt->dev->stats.tx_errors++;694 695 amt_update_gw_status(amt, AMT_STATUS_SENT_DISCOVERY, true);696out:697 rcu_read_unlock();698}699 700static void amt_send_request(struct amt_dev *amt, bool v6)701{702 struct amt_header_request *amtrh;703 int hlen, tlen, offset;704 struct socket *sock;705 struct udphdr *udph;706 struct sk_buff *skb;707 struct iphdr *iph;708 struct rtable *rt;709 struct flowi4 fl4;710 u32 len;711 int err;712 713 rcu_read_lock();714 sock = rcu_dereference(amt->sock);715 if (!sock)716 goto out;717 718 if (!netif_running(amt->stream_dev) || !netif_running(amt->dev))719 goto out;720 721 rt = ip_route_output_ports(amt->net, &fl4, sock->sk,722 amt->remote_ip, amt->local_ip,723 amt->gw_port, amt->relay_port,724 IPPROTO_UDP, 0,725 amt->stream_dev->ifindex);726 if (IS_ERR(rt)) {727 amt->dev->stats.tx_errors++;728 goto out;729 }730 731 hlen = LL_RESERVED_SPACE(amt->dev);732 tlen = amt->dev->needed_tailroom;733 len = hlen + tlen + sizeof(*iph) + sizeof(*udph) + sizeof(*amtrh);734 skb = netdev_alloc_skb_ip_align(amt->dev, len);735 if (!skb) {736 ip_rt_put(rt);737 amt->dev->stats.tx_errors++;738 goto out;739 }740 741 skb->priority = TC_PRIO_CONTROL;742 skb_dst_set(skb, &rt->dst);743 744 len = sizeof(*iph) + sizeof(*udph) + sizeof(*amtrh);745 skb_reset_network_header(skb);746 skb_put(skb, len);747 amtrh = skb_pull(skb, sizeof(*iph) + sizeof(*udph));748 amtrh->version = 0;749 amtrh->type = AMT_MSG_REQUEST;750 amtrh->reserved1 = 0;751 amtrh->p = v6;752 amtrh->reserved2 = 0;753 amtrh->nonce = amt->nonce;754 skb_push(skb, sizeof(*udph));755 skb_reset_transport_header(skb);756 udph = udp_hdr(skb);757 udph->source = amt->gw_port;758 udph->dest = amt->relay_port;759 udph->len = htons(sizeof(*amtrh) + sizeof(*udph));760 udph->check = 0;761 offset = skb_transport_offset(skb);762 skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);763 udph->check = csum_tcpudp_magic(amt->local_ip, amt->remote_ip,764 sizeof(*udph) + sizeof(*amtrh),765 IPPROTO_UDP, skb->csum);766 767 skb_push(skb, sizeof(*iph));768 iph = ip_hdr(skb);769 iph->version = 4;770 iph->ihl = (sizeof(struct iphdr)) >> 2;771 iph->tos = AMT_TOS;772 iph->frag_off = 0;773 iph->ttl = ip4_dst_hoplimit(&rt->dst);774 iph->daddr = amt->remote_ip;775 iph->saddr = amt->local_ip;776 iph->protocol = IPPROTO_UDP;777 iph->tot_len = htons(len);778 779 skb->ip_summed = CHECKSUM_NONE;780 ip_select_ident(amt->net, skb, NULL);781 ip_send_check(iph);782 err = ip_local_out(amt->net, sock->sk, skb);783 if (unlikely(net_xmit_eval(err)))784 amt->dev->stats.tx_errors++;785 786out:787 rcu_read_unlock();788}789 790static void amt_send_igmp_gq(struct amt_dev *amt,791 struct amt_tunnel_list *tunnel)792{793 struct sk_buff *skb;794 795 skb = amt_build_igmp_gq(amt);796 if (!skb)797 return;798 799 amt_skb_cb(skb)->tunnel = tunnel;800 dev_queue_xmit(skb);801}802 803#if IS_ENABLED(CONFIG_IPV6)804static struct sk_buff *amt_build_mld_gq(struct amt_dev *amt)805{806 u8 ra[AMT_IP6HDR_OPTS] = { IPPROTO_ICMPV6, 0, IPV6_TLV_ROUTERALERT,807 2, 0, 0, IPV6_TLV_PAD1, IPV6_TLV_PAD1 };808 int hlen = LL_RESERVED_SPACE(amt->dev);809 int tlen = amt->dev->needed_tailroom;810 struct mld2_query *mld2q;811 void *csum_start = NULL;812 struct ipv6hdr *ip6h;813 struct sk_buff *skb;814 struct ethhdr *eth;815 u32 len;816 817 len = hlen + tlen + sizeof(*ip6h) + sizeof(ra) + sizeof(*mld2q);818 skb = netdev_alloc_skb_ip_align(amt->dev, len);819 if (!skb)820 return NULL;821 822 skb_reserve(skb, hlen);823 skb_push(skb, sizeof(*eth));824 skb_reset_mac_header(skb);825 eth = eth_hdr(skb);826 skb->priority = TC_PRIO_CONTROL;827 skb->protocol = htons(ETH_P_IPV6);828 skb_put_zero(skb, sizeof(*ip6h));829 skb_put_data(skb, ra, sizeof(ra));830 skb_put_zero(skb, sizeof(*mld2q));831 skb_pull(skb, sizeof(*eth));832 skb_reset_network_header(skb);833 ip6h = ipv6_hdr(skb);834 ip6h->payload_len = htons(sizeof(ra) + sizeof(*mld2q));835 ip6h->nexthdr = NEXTHDR_HOP;836 ip6h->hop_limit = 1;837 ip6h->daddr = mld2_all_node;838 ip6_flow_hdr(ip6h, 0, 0);839 840 if (ipv6_dev_get_saddr(amt->net, amt->dev, &ip6h->daddr, 0,841 &ip6h->saddr)) {842 amt->dev->stats.tx_errors++;843 kfree_skb(skb);844 return NULL;845 }846 847 eth->h_proto = htons(ETH_P_IPV6);848 ether_addr_copy(eth->h_source, amt->dev->dev_addr);849 ipv6_eth_mc_map(&mld2_all_node, eth->h_dest);850 851 skb_pull(skb, sizeof(*ip6h) + sizeof(ra));852 skb_reset_transport_header(skb);853 mld2q = (struct mld2_query *)icmp6_hdr(skb);854 mld2q->mld2q_mrc = htons(1);855 mld2q->mld2q_type = ICMPV6_MGM_QUERY;856 mld2q->mld2q_code = 0;857 mld2q->mld2q_cksum = 0;858 mld2q->mld2q_resv1 = 0;859 mld2q->mld2q_resv2 = 0;860 mld2q->mld2q_suppress = 0;861 mld2q->mld2q_qrv = amt->qrv;862 mld2q->mld2q_nsrcs = 0;863 mld2q->mld2q_qqic = amt->qi;864 csum_start = (void *)mld2q;865 mld2q->mld2q_cksum = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,866 sizeof(*mld2q),867 IPPROTO_ICMPV6,868 csum_partial(csum_start,869 sizeof(*mld2q), 0));870 871 skb->ip_summed = CHECKSUM_NONE;872 skb_push(skb, sizeof(*eth) + sizeof(*ip6h) + sizeof(ra));873 return skb;874}875 876static void amt_send_mld_gq(struct amt_dev *amt, struct amt_tunnel_list *tunnel)877{878 struct sk_buff *skb;879 880 skb = amt_build_mld_gq(amt);881 if (!skb)882 return;883 884 amt_skb_cb(skb)->tunnel = tunnel;885 dev_queue_xmit(skb);886}887#else888static void amt_send_mld_gq(struct amt_dev *amt, struct amt_tunnel_list *tunnel)889{890}891#endif892 893static bool amt_queue_event(struct amt_dev *amt, enum amt_event event,894 struct sk_buff *skb)895{896 int index;897 898 spin_lock_bh(&amt->lock);899 if (amt->nr_events >= AMT_MAX_EVENTS) {900 spin_unlock_bh(&amt->lock);901 return 1;902 }903 904 index = (amt->event_idx + amt->nr_events) % AMT_MAX_EVENTS;905 amt->events[index].event = event;906 amt->events[index].skb = skb;907 amt->nr_events++;908 amt->event_idx %= AMT_MAX_EVENTS;909 queue_work(amt_wq, &amt->event_wq);910 spin_unlock_bh(&amt->lock);911 912 return 0;913}914 915static void amt_secret_work(struct work_struct *work)916{917 struct amt_dev *amt = container_of(to_delayed_work(work),918 struct amt_dev,919 secret_wq);920 921 spin_lock_bh(&amt->lock);922 get_random_bytes(&amt->key, sizeof(siphash_key_t));923 spin_unlock_bh(&amt->lock);924 mod_delayed_work(amt_wq, &amt->secret_wq,925 msecs_to_jiffies(AMT_SECRET_TIMEOUT));926}927 928static void amt_event_send_discovery(struct amt_dev *amt)929{930 if (amt->status > AMT_STATUS_SENT_DISCOVERY)931 goto out;932 get_random_bytes(&amt->nonce, sizeof(__be32));933 934 amt_send_discovery(amt);935out:936 mod_delayed_work(amt_wq, &amt->discovery_wq,937 msecs_to_jiffies(AMT_DISCOVERY_TIMEOUT));938}939 940static void amt_discovery_work(struct work_struct *work)941{942 struct amt_dev *amt = container_of(to_delayed_work(work),943 struct amt_dev,944 discovery_wq);945 946 if (amt_queue_event(amt, AMT_EVENT_SEND_DISCOVERY, NULL))947 mod_delayed_work(amt_wq, &amt->discovery_wq,948 msecs_to_jiffies(AMT_DISCOVERY_TIMEOUT));949}950 951static void amt_event_send_request(struct amt_dev *amt)952{953 u32 exp;954 955 if (amt->status < AMT_STATUS_RECEIVED_ADVERTISEMENT)956 goto out;957 958 if (amt->req_cnt > AMT_MAX_REQ_COUNT) {959 netdev_dbg(amt->dev, "Gateway is not ready");960 amt->qi = AMT_INIT_REQ_TIMEOUT;961 WRITE_ONCE(amt->ready4, false);962 WRITE_ONCE(amt->ready6, false);963 amt->remote_ip = 0;964 amt_update_gw_status(amt, AMT_STATUS_INIT, false);965 amt->req_cnt = 0;966 amt->nonce = 0;967 goto out;968 }969 970 if (!amt->req_cnt) {971 WRITE_ONCE(amt->ready4, false);972 WRITE_ONCE(amt->ready6, false);973 get_random_bytes(&amt->nonce, sizeof(__be32));974 }975 976 amt_send_request(amt, false);977 amt_send_request(amt, true);978 amt_update_gw_status(amt, AMT_STATUS_SENT_REQUEST, true);979 amt->req_cnt++;980out:981 exp = min_t(u32, (1 * (1 << amt->req_cnt)), AMT_MAX_REQ_TIMEOUT);982 mod_delayed_work(amt_wq, &amt->req_wq, msecs_to_jiffies(exp * 1000));983}984 985static void amt_req_work(struct work_struct *work)986{987 struct amt_dev *amt = container_of(to_delayed_work(work),988 struct amt_dev,989 req_wq);990 991 if (amt_queue_event(amt, AMT_EVENT_SEND_REQUEST, NULL))992 mod_delayed_work(amt_wq, &amt->req_wq,993 msecs_to_jiffies(100));994}995 996static bool amt_send_membership_update(struct amt_dev *amt,997 struct sk_buff *skb,998 bool v6)999{1000 struct amt_header_membership_update *amtmu;1001 struct socket *sock;1002 struct iphdr *iph;1003 struct flowi4 fl4;1004 struct rtable *rt;1005 int err;1006 1007 sock = rcu_dereference_bh(amt->sock);1008 if (!sock)1009 return true;1010 1011 err = skb_cow_head(skb, LL_RESERVED_SPACE(amt->dev) + sizeof(*amtmu) +1012 sizeof(*iph) + sizeof(struct udphdr));1013 if (err)1014 return true;1015 1016 skb_reset_inner_headers(skb);1017 memset(&fl4, 0, sizeof(struct flowi4));1018 fl4.flowi4_oif = amt->stream_dev->ifindex;1019 fl4.daddr = amt->remote_ip;1020 fl4.saddr = amt->local_ip;1021 fl4.flowi4_tos = AMT_TOS;1022 fl4.flowi4_proto = IPPROTO_UDP;1023 rt = ip_route_output_key(amt->net, &fl4);1024 if (IS_ERR(rt)) {1025 netdev_dbg(amt->dev, "no route to %pI4\n", &amt->remote_ip);1026 return true;1027 }1028 1029 amtmu = skb_push(skb, sizeof(*amtmu));1030 amtmu->version = 0;1031 amtmu->type = AMT_MSG_MEMBERSHIP_UPDATE;1032 amtmu->reserved = 0;1033 amtmu->nonce = amt->nonce;1034 amtmu->response_mac = amt->mac;1035 1036 if (!v6)1037 skb_set_inner_protocol(skb, htons(ETH_P_IP));1038 else1039 skb_set_inner_protocol(skb, htons(ETH_P_IPV6));1040 udp_tunnel_xmit_skb(rt, sock->sk, skb,1041 fl4.saddr,1042 fl4.daddr,1043 AMT_TOS,1044 ip4_dst_hoplimit(&rt->dst),1045 0,1046 amt->gw_port,1047 amt->relay_port,1048 false,1049 false);1050 amt_update_gw_status(amt, AMT_STATUS_SENT_UPDATE, true);1051 return false;1052}1053 1054static void amt_send_multicast_data(struct amt_dev *amt,1055 const struct sk_buff *oskb,1056 struct amt_tunnel_list *tunnel,1057 bool v6)1058{1059 struct amt_header_mcast_data *amtmd;1060 struct socket *sock;1061 struct sk_buff *skb;1062 struct iphdr *iph;1063 struct flowi4 fl4;1064 struct rtable *rt;1065 1066 sock = rcu_dereference_bh(amt->sock);1067 if (!sock)1068 return;1069 1070 skb = skb_copy_expand(oskb, sizeof(*amtmd) + sizeof(*iph) +1071 sizeof(struct udphdr), 0, GFP_ATOMIC);1072 if (!skb)1073 return;1074 1075 skb_reset_inner_headers(skb);1076 memset(&fl4, 0, sizeof(struct flowi4));1077 fl4.flowi4_oif = amt->stream_dev->ifindex;1078 fl4.daddr = tunnel->ip4;1079 fl4.saddr = amt->local_ip;1080 fl4.flowi4_proto = IPPROTO_UDP;1081 rt = ip_route_output_key(amt->net, &fl4);1082 if (IS_ERR(rt)) {1083 netdev_dbg(amt->dev, "no route to %pI4\n", &tunnel->ip4);1084 kfree_skb(skb);1085 return;1086 }1087 1088 amtmd = skb_push(skb, sizeof(*amtmd));1089 amtmd->version = 0;1090 amtmd->reserved = 0;1091 amtmd->type = AMT_MSG_MULTICAST_DATA;1092 1093 if (!v6)1094 skb_set_inner_protocol(skb, htons(ETH_P_IP));1095 else1096 skb_set_inner_protocol(skb, htons(ETH_P_IPV6));1097 udp_tunnel_xmit_skb(rt, sock->sk, skb,1098 fl4.saddr,1099 fl4.daddr,1100 AMT_TOS,1101 ip4_dst_hoplimit(&rt->dst),1102 0,1103 amt->relay_port,1104 tunnel->source_port,1105 false,1106 false);1107}1108 1109static bool amt_send_membership_query(struct amt_dev *amt,1110 struct sk_buff *skb,1111 struct amt_tunnel_list *tunnel,1112 bool v6)1113{1114 struct amt_header_membership_query *amtmq;1115 struct socket *sock;1116 struct rtable *rt;1117 struct flowi4 fl4;1118 int err;1119 1120 sock = rcu_dereference_bh(amt->sock);1121 if (!sock)1122 return true;1123 1124 err = skb_cow_head(skb, LL_RESERVED_SPACE(amt->dev) + sizeof(*amtmq) +1125 sizeof(struct iphdr) + sizeof(struct udphdr));1126 if (err)1127 return true;1128 1129 skb_reset_inner_headers(skb);1130 memset(&fl4, 0, sizeof(struct flowi4));1131 fl4.flowi4_oif = amt->stream_dev->ifindex;1132 fl4.daddr = tunnel->ip4;1133 fl4.saddr = amt->local_ip;1134 fl4.flowi4_tos = AMT_TOS;1135 fl4.flowi4_proto = IPPROTO_UDP;1136 rt = ip_route_output_key(amt->net, &fl4);1137 if (IS_ERR(rt)) {1138 netdev_dbg(amt->dev, "no route to %pI4\n", &tunnel->ip4);1139 return true;1140 }1141 1142 amtmq = skb_push(skb, sizeof(*amtmq));1143 amtmq->version = 0;1144 amtmq->type = AMT_MSG_MEMBERSHIP_QUERY;1145 amtmq->reserved = 0;1146 amtmq->l = 0;1147 amtmq->g = 0;1148 amtmq->nonce = tunnel->nonce;1149 amtmq->response_mac = tunnel->mac;1150 1151 if (!v6)1152 skb_set_inner_protocol(skb, htons(ETH_P_IP));1153 else1154 skb_set_inner_protocol(skb, htons(ETH_P_IPV6));1155 udp_tunnel_xmit_skb(rt, sock->sk, skb,1156 fl4.saddr,1157 fl4.daddr,1158 AMT_TOS,1159 ip4_dst_hoplimit(&rt->dst),1160 0,1161 amt->relay_port,1162 tunnel->source_port,1163 false,1164 false);1165 amt_update_relay_status(tunnel, AMT_STATUS_SENT_QUERY, true);1166 return false;1167}1168 1169static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev)1170{1171 struct amt_dev *amt = netdev_priv(dev);1172 struct amt_tunnel_list *tunnel;1173 struct amt_group_node *gnode;1174 union amt_addr group = {0,};1175#if IS_ENABLED(CONFIG_IPV6)1176 struct ipv6hdr *ip6h;1177 struct mld_msg *mld;1178#endif1179 bool report = false;1180 struct igmphdr *ih;1181 bool query = false;1182 struct iphdr *iph;1183 bool data = false;1184 bool v6 = false;1185 u32 hash;1186 1187 iph = ip_hdr(skb);1188 if (iph->version == 4) {1189 if (!ipv4_is_multicast(iph->daddr))1190 goto free;1191 1192 if (!ip_mc_check_igmp(skb)) {1193 ih = igmp_hdr(skb);1194 switch (ih->type) {1195 case IGMPV3_HOST_MEMBERSHIP_REPORT:1196 case IGMP_HOST_MEMBERSHIP_REPORT:1197 report = true;1198 break;1199 case IGMP_HOST_MEMBERSHIP_QUERY:1200 query = true;1201 break;1202 default:1203 goto free;1204 }1205 } else {1206 data = true;1207 }1208 v6 = false;1209 group.ip4 = iph->daddr;1210#if IS_ENABLED(CONFIG_IPV6)1211 } else if (iph->version == 6) {1212 ip6h = ipv6_hdr(skb);1213 if (!ipv6_addr_is_multicast(&ip6h->daddr))1214 goto free;1215 1216 if (!ipv6_mc_check_mld(skb)) {1217 mld = (struct mld_msg *)skb_transport_header(skb);1218 switch (mld->mld_type) {1219 case ICMPV6_MGM_REPORT:1220 case ICMPV6_MLD2_REPORT:1221 report = true;1222 break;1223 case ICMPV6_MGM_QUERY:1224 query = true;1225 break;1226 default:1227 goto free;1228 }1229 } else {1230 data = true;1231 }1232 v6 = true;1233 group.ip6 = ip6h->daddr;1234#endif1235 } else {1236 dev->stats.tx_errors++;1237 goto free;1238 }1239 1240 if (!pskb_may_pull(skb, sizeof(struct ethhdr)))1241 goto free;1242 1243 skb_pull(skb, sizeof(struct ethhdr));1244 1245 if (amt->mode == AMT_MODE_GATEWAY) {1246 /* Gateway only passes IGMP/MLD packets */1247 if (!report)1248 goto free;1249 if ((!v6 && !READ_ONCE(amt->ready4)) ||1250 (v6 && !READ_ONCE(amt->ready6)))1251 goto free;1252 if (amt_send_membership_update(amt, skb, v6))1253 goto free;1254 goto unlock;1255 } else if (amt->mode == AMT_MODE_RELAY) {1256 if (query) {1257 tunnel = amt_skb_cb(skb)->tunnel;1258 if (!tunnel) {1259 WARN_ON(1);1260 goto free;1261 }1262 1263 /* Do not forward unexpected query */1264 if (amt_send_membership_query(amt, skb, tunnel, v6))1265 goto free;1266 goto unlock;1267 }1268 1269 if (!data)1270 goto free;1271 list_for_each_entry_rcu(tunnel, &amt->tunnel_list, list) {1272 hash = amt_group_hash(tunnel, &group);1273 hlist_for_each_entry_rcu(gnode, &tunnel->groups[hash],1274 node) {1275 if (!v6) {1276 if (gnode->group_addr.ip4 == iph->daddr)1277 goto found;1278#if IS_ENABLED(CONFIG_IPV6)1279 } else {1280 if (ipv6_addr_equal(&gnode->group_addr.ip6,1281 &ip6h->daddr))1282 goto found;1283#endif1284 }1285 }1286 continue;1287found:1288 amt_send_multicast_data(amt, skb, tunnel, v6);1289 }1290 }1291 1292 dev_kfree_skb(skb);1293 return NETDEV_TX_OK;1294free:1295 dev_kfree_skb(skb);1296unlock:1297 dev->stats.tx_dropped++;1298 return NETDEV_TX_OK;1299}1300 1301static int amt_parse_type(struct sk_buff *skb)1302{1303 struct amt_header *amth;1304 1305 if (!pskb_may_pull(skb, sizeof(struct udphdr) +1306 sizeof(struct amt_header)))1307 return -1;1308 1309 amth = (struct amt_header *)(udp_hdr(skb) + 1);1310 1311 if (amth->version != 0)1312 return -1;1313 1314 if (amth->type >= __AMT_MSG_MAX || !amth->type)1315 return -1;1316 return amth->type;1317}1318 1319static void amt_clear_groups(struct amt_tunnel_list *tunnel)1320{1321 struct amt_dev *amt = tunnel->amt;1322 struct amt_group_node *gnode;1323 struct hlist_node *t;1324 int i;1325 1326 spin_lock_bh(&tunnel->lock);1327 rcu_read_lock();1328 for (i = 0; i < amt->hash_buckets; i++)1329 hlist_for_each_entry_safe(gnode, t, &tunnel->groups[i], node)1330 amt_del_group(amt, gnode);1331 rcu_read_unlock();1332 spin_unlock_bh(&tunnel->lock);1333}1334 1335static void amt_tunnel_expire(struct work_struct *work)1336{1337 struct amt_tunnel_list *tunnel = container_of(to_delayed_work(work),1338 struct amt_tunnel_list,1339 gc_wq);1340 struct amt_dev *amt = tunnel->amt;1341 1342 spin_lock_bh(&amt->lock);1343 rcu_read_lock();1344 list_del_rcu(&tunnel->list);1345 amt->nr_tunnels--;1346 amt_clear_groups(tunnel);1347 rcu_read_unlock();1348 spin_unlock_bh(&amt->lock);1349 kfree_rcu(tunnel, rcu);1350}1351 1352static void amt_cleanup_srcs(struct amt_dev *amt,1353 struct amt_tunnel_list *tunnel,1354 struct amt_group_node *gnode)1355{1356 struct amt_source_node *snode;1357 struct hlist_node *t;1358 int i;1359 1360 /* Delete old sources */1361 for (i = 0; i < amt->hash_buckets; i++) {1362 hlist_for_each_entry_safe(snode, t, &gnode->sources[i], node) {1363 if (snode->flags == AMT_SOURCE_OLD)1364 amt_destroy_source(snode);1365 }1366 }1367 1368 /* switch from new to old */1369 for (i = 0; i < amt->hash_buckets; i++) {1370 hlist_for_each_entry_rcu(snode, &gnode->sources[i], node) {1371 snode->flags = AMT_SOURCE_OLD;1372 if (!gnode->v6)1373 netdev_dbg(snode->gnode->amt->dev,1374 "Add source as OLD %pI4 from %pI4\n",1375 &snode->source_addr.ip4,1376 &gnode->group_addr.ip4);1377#if IS_ENABLED(CONFIG_IPV6)1378 else1379 netdev_dbg(snode->gnode->amt->dev,1380 "Add source as OLD %pI6 from %pI6\n",1381 &snode->source_addr.ip6,1382 &gnode->group_addr.ip6);1383#endif1384 }1385 }1386}1387 1388static void amt_add_srcs(struct amt_dev *amt, struct amt_tunnel_list *tunnel,1389 struct amt_group_node *gnode, void *grec,1390 bool v6)1391{1392 struct igmpv3_grec *igmp_grec;1393 struct amt_source_node *snode;1394#if IS_ENABLED(CONFIG_IPV6)1395 struct mld2_grec *mld_grec;1396#endif1397 union amt_addr src = {0,};1398 u16 nsrcs;1399 u32 hash;1400 int i;1401 1402 if (!v6) {1403 igmp_grec = grec;1404 nsrcs = ntohs(igmp_grec->grec_nsrcs);1405 } else {1406#if IS_ENABLED(CONFIG_IPV6)1407 mld_grec = grec;1408 nsrcs = ntohs(mld_grec->grec_nsrcs);1409#else1410 return;1411#endif1412 }1413 for (i = 0; i < nsrcs; i++) {1414 if (tunnel->nr_sources >= amt->max_sources)1415 return;1416 if (!v6)1417 src.ip4 = igmp_grec->grec_src[i];1418#if IS_ENABLED(CONFIG_IPV6)1419 else1420 memcpy(&src.ip6, &mld_grec->grec_src[i],1421 sizeof(struct in6_addr));1422#endif1423 if (amt_lookup_src(tunnel, gnode, AMT_FILTER_ALL, &src))1424 continue;1425 1426 snode = amt_alloc_snode(gnode, &src);1427 if (snode) {1428 hash = amt_source_hash(tunnel, &snode->source_addr);1429 hlist_add_head_rcu(&snode->node, &gnode->sources[hash]);1430 tunnel->nr_sources++;1431 gnode->nr_sources++;1432 1433 if (!gnode->v6)1434 netdev_dbg(snode->gnode->amt->dev,1435 "Add source as NEW %pI4 from %pI4\n",1436 &snode->source_addr.ip4,1437 &gnode->group_addr.ip4);1438#if IS_ENABLED(CONFIG_IPV6)1439 else1440 netdev_dbg(snode->gnode->amt->dev,1441 "Add source as NEW %pI6 from %pI6\n",1442 &snode->source_addr.ip6,1443 &gnode->group_addr.ip6);1444#endif1445 }1446 }1447}1448 1449/* Router State Report Rec'd New Router State1450 * ------------ ------------ ----------------1451 * EXCLUDE (X,Y) IS_IN (A) EXCLUDE (X+A,Y-A)1452 *1453 * -----------+-----------+-----------+1454 * | OLD | NEW |1455 * -----------+-----------+-----------+1456 * FWD | X | X+A |1457 * -----------+-----------+-----------+1458 * D_FWD | Y | Y-A |1459 * -----------+-----------+-----------+1460 * NONE | | A |1461 * -----------+-----------+-----------+1462 *1463 * a) Received sources are NONE/NEW1464 * b) All NONE will be deleted by amt_cleanup_srcs().1465 * c) All OLD will be deleted by amt_cleanup_srcs().1466 * d) After delete, NEW source will be switched to OLD.1467 */1468static void amt_lookup_act_srcs(struct amt_tunnel_list *tunnel,1469 struct amt_group_node *gnode,1470 void *grec,1471 enum amt_ops ops,1472 enum amt_filter filter,1473 enum amt_act act,1474 bool v6)1475{1476 struct amt_dev *amt = tunnel->amt;1477 struct amt_source_node *snode;1478 struct igmpv3_grec *igmp_grec;1479#if IS_ENABLED(CONFIG_IPV6)1480 struct mld2_grec *mld_grec;1481#endif1482 union amt_addr src = {0,};1483 struct hlist_node *t;1484 u16 nsrcs;1485 int i, j;1486 1487 if (!v6) {1488 igmp_grec = grec;1489 nsrcs = ntohs(igmp_grec->grec_nsrcs);1490 } else {1491#if IS_ENABLED(CONFIG_IPV6)1492 mld_grec = grec;1493 nsrcs = ntohs(mld_grec->grec_nsrcs);1494#else1495 return;1496#endif1497 }1498 1499 memset(&src, 0, sizeof(union amt_addr));1500 switch (ops) {1501 case AMT_OPS_INT:1502 /* A*B */1503 for (i = 0; i < nsrcs; i++) {1504 if (!v6)1505 src.ip4 = igmp_grec->grec_src[i];1506#if IS_ENABLED(CONFIG_IPV6)1507 else1508 memcpy(&src.ip6, &mld_grec->grec_src[i],1509 sizeof(struct in6_addr));1510#endif1511 snode = amt_lookup_src(tunnel, gnode, filter, &src);1512 if (!snode)1513 continue;1514 amt_act_src(tunnel, gnode, snode, act);1515 }1516 break;1517 case AMT_OPS_UNI:1518 /* A+B */1519 for (i = 0; i < amt->hash_buckets; i++) {1520 hlist_for_each_entry_safe(snode, t, &gnode->sources[i],1521 node) {1522 if (amt_status_filter(snode, filter))1523 amt_act_src(tunnel, gnode, snode, act);1524 }1525 }1526 for (i = 0; i < nsrcs; i++) {1527 if (!v6)1528 src.ip4 = igmp_grec->grec_src[i];1529#if IS_ENABLED(CONFIG_IPV6)1530 else1531 memcpy(&src.ip6, &mld_grec->grec_src[i],1532 sizeof(struct in6_addr));1533#endif1534 snode = amt_lookup_src(tunnel, gnode, filter, &src);1535 if (!snode)1536 continue;1537 amt_act_src(tunnel, gnode, snode, act);1538 }1539 break;1540 case AMT_OPS_SUB:1541 /* A-B */1542 for (i = 0; i < amt->hash_buckets; i++) {1543 hlist_for_each_entry_safe(snode, t, &gnode->sources[i],1544 node) {1545 if (!amt_status_filter(snode, filter))1546 continue;1547 for (j = 0; j < nsrcs; j++) {1548 if (!v6)1549 src.ip4 = igmp_grec->grec_src[j];1550#if IS_ENABLED(CONFIG_IPV6)1551 else1552 memcpy(&src.ip6,1553 &mld_grec->grec_src[j],1554 sizeof(struct in6_addr));1555#endif1556 if (amt_addr_equal(&snode->source_addr,1557 &src))1558 goto out_sub;1559 }1560 amt_act_src(tunnel, gnode, snode, act);1561 continue;1562out_sub:;1563 }1564 }1565 break;1566 case AMT_OPS_SUB_REV:1567 /* B-A */1568 for (i = 0; i < nsrcs; i++) {1569 if (!v6)1570 src.ip4 = igmp_grec->grec_src[i];1571#if IS_ENABLED(CONFIG_IPV6)1572 else1573 memcpy(&src.ip6, &mld_grec->grec_src[i],1574 sizeof(struct in6_addr));1575#endif1576 snode = amt_lookup_src(tunnel, gnode, AMT_FILTER_ALL,1577 &src);1578 if (!snode) {1579 snode = amt_lookup_src(tunnel, gnode,1580 filter, &src);1581 if (snode)1582 amt_act_src(tunnel, gnode, snode, act);1583 }1584 }1585 break;1586 default:1587 netdev_dbg(amt->dev, "Invalid type\n");1588 return;1589 }1590}1591 1592static void amt_mcast_is_in_handler(struct amt_dev *amt,1593 struct amt_tunnel_list *tunnel,1594 struct amt_group_node *gnode,1595 void *grec, void *zero_grec, bool v6)1596{1597 if (gnode->filter_mode == MCAST_INCLUDE) {1598/* Router State Report Rec'd New Router State Actions1599 * ------------ ------------ ---------------- -------1600 * INCLUDE (A) IS_IN (B) INCLUDE (A+B) (B)=GMI1601 */1602 /* Update IS_IN (B) as FWD/NEW */1603 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_UNI,1604 AMT_FILTER_NONE_NEW,1605 AMT_ACT_STATUS_FWD_NEW,1606 v6);1607 /* Update INCLUDE (A) as NEW */1608 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_UNI,1609 AMT_FILTER_FWD,1610 AMT_ACT_STATUS_FWD_NEW,1611 v6);1612 /* (B)=GMI */1613 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_INT,1614 AMT_FILTER_FWD_NEW,1615 AMT_ACT_GMI,1616 v6);1617 } else {1618/* State Actions1619 * ------------ ------------ ---------------- -------1620 * EXCLUDE (X,Y) IS_IN (A) EXCLUDE (X+A,Y-A) (A)=GMI1621 */1622 /* Update (A) in (X, Y) as NONE/NEW */1623 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_INT,1624 AMT_FILTER_BOTH,1625 AMT_ACT_STATUS_NONE_NEW,1626 v6);1627 /* Update FWD/OLD as FWD/NEW */1628 amt_lookup_act_srcs(tunnel, gnode, zero_grec, AMT_OPS_UNI,1629 AMT_FILTER_FWD,1630 AMT_ACT_STATUS_FWD_NEW,1631 v6);1632 /* Update IS_IN (A) as FWD/NEW */1633 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_INT,1634 AMT_FILTER_NONE_NEW,1635 AMT_ACT_STATUS_FWD_NEW,1636 v6);1637 /* Update EXCLUDE (, Y-A) as D_FWD_NEW */1638 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_SUB,1639 AMT_FILTER_D_FWD,1640 AMT_ACT_STATUS_D_FWD_NEW,1641 v6);1642 }1643}1644 1645static void amt_mcast_is_ex_handler(struct amt_dev *amt,1646 struct amt_tunnel_list *tunnel,1647 struct amt_group_node *gnode,1648 void *grec, void *zero_grec, bool v6)1649{1650 if (gnode->filter_mode == MCAST_INCLUDE) {1651/* Router State Report Rec'd New Router State Actions1652 * ------------ ------------ ---------------- -------1653 * INCLUDE (A) IS_EX (B) EXCLUDE (A*B,B-A) (B-A)=01654 * Delete (A-B)1655 * Group Timer=GMI1656 */1657 /* EXCLUDE(A*B, ) */1658 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_INT,1659 AMT_FILTER_FWD,1660 AMT_ACT_STATUS_FWD_NEW,1661 v6);1662 /* EXCLUDE(, B-A) */1663 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_SUB_REV,1664 AMT_FILTER_FWD,1665 AMT_ACT_STATUS_D_FWD_NEW,1666 v6);1667 /* (B-A)=0 */1668 amt_lookup_act_srcs(tunnel, gnode, zero_grec, AMT_OPS_UNI,1669 AMT_FILTER_D_FWD_NEW,1670 AMT_ACT_GMI_ZERO,1671 v6);1672 /* Group Timer=GMI */1673 if (!mod_delayed_work(amt_wq, &gnode->group_timer,1674 msecs_to_jiffies(amt_gmi(amt))))1675 dev_hold(amt->dev);1676 gnode->filter_mode = MCAST_EXCLUDE;1677 /* Delete (A-B) will be worked by amt_cleanup_srcs(). */1678 } else {1679/* Router State Report Rec'd New Router State Actions1680 * ------------ ------------ ---------------- -------1681 * EXCLUDE (X,Y) IS_EX (A) EXCLUDE (A-Y,Y*A) (A-X-Y)=GMI1682 * Delete (X-A)1683 * Delete (Y-A)1684 * Group Timer=GMI1685 */1686 /* EXCLUDE (A-Y, ) */1687 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_SUB_REV,1688 AMT_FILTER_D_FWD,1689 AMT_ACT_STATUS_FWD_NEW,1690 v6);1691 /* EXCLUDE (, Y*A ) */1692 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_INT,1693 AMT_FILTER_D_FWD,1694 AMT_ACT_STATUS_D_FWD_NEW,1695 v6);1696 /* (A-X-Y)=GMI */1697 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_SUB_REV,1698 AMT_FILTER_BOTH_NEW,1699 AMT_ACT_GMI,1700 v6);1701 /* Group Timer=GMI */1702 if (!mod_delayed_work(amt_wq, &gnode->group_timer,1703 msecs_to_jiffies(amt_gmi(amt))))1704 dev_hold(amt->dev);1705 /* Delete (X-A), (Y-A) will be worked by amt_cleanup_srcs(). */1706 }1707}1708 1709static void amt_mcast_to_in_handler(struct amt_dev *amt,1710 struct amt_tunnel_list *tunnel,1711 struct amt_group_node *gnode,1712 void *grec, void *zero_grec, bool v6)1713{1714 if (gnode->filter_mode == MCAST_INCLUDE) {1715/* Router State Report Rec'd New Router State Actions1716 * ------------ ------------ ---------------- -------1717 * INCLUDE (A) TO_IN (B) INCLUDE (A+B) (B)=GMI1718 * Send Q(G,A-B)1719 */1720 /* Update TO_IN (B) sources as FWD/NEW */1721 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_UNI,1722 AMT_FILTER_NONE_NEW,1723 AMT_ACT_STATUS_FWD_NEW,1724 v6);1725 /* Update INCLUDE (A) sources as NEW */1726 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_UNI,1727 AMT_FILTER_FWD,1728 AMT_ACT_STATUS_FWD_NEW,1729 v6);1730 /* (B)=GMI */1731 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_INT,1732 AMT_FILTER_FWD_NEW,1733 AMT_ACT_GMI,1734 v6);1735 } else {1736/* Router State Report Rec'd New Router State Actions1737 * ------------ ------------ ---------------- -------1738 * EXCLUDE (X,Y) TO_IN (A) EXCLUDE (X+A,Y-A) (A)=GMI1739 * Send Q(G,X-A)1740 * Send Q(G)1741 */1742 /* Update TO_IN (A) sources as FWD/NEW */1743 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_UNI,1744 AMT_FILTER_NONE_NEW,1745 AMT_ACT_STATUS_FWD_NEW,1746 v6);1747 /* Update EXCLUDE(X,) sources as FWD/NEW */1748 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_UNI,1749 AMT_FILTER_FWD,1750 AMT_ACT_STATUS_FWD_NEW,1751 v6);1752 /* EXCLUDE (, Y-A)1753 * (A) are already switched to FWD_NEW.1754 * So, D_FWD/OLD -> D_FWD/NEW is okay.1755 */1756 amt_lookup_act_srcs(tunnel, gnode, zero_grec, AMT_OPS_UNI,1757 AMT_FILTER_D_FWD,1758 AMT_ACT_STATUS_D_FWD_NEW,1759 v6);1760 /* (A)=GMI1761 * Only FWD_NEW will have (A) sources.1762 */1763 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_INT,1764 AMT_FILTER_FWD_NEW,1765 AMT_ACT_GMI,1766 v6);1767 }1768}1769 1770static void amt_mcast_to_ex_handler(struct amt_dev *amt,1771 struct amt_tunnel_list *tunnel,1772 struct amt_group_node *gnode,1773 void *grec, void *zero_grec, bool v6)1774{1775 if (gnode->filter_mode == MCAST_INCLUDE) {1776/* Router State Report Rec'd New Router State Actions1777 * ------------ ------------ ---------------- -------1778 * INCLUDE (A) TO_EX (B) EXCLUDE (A*B,B-A) (B-A)=01779 * Delete (A-B)1780 * Send Q(G,A*B)1781 * Group Timer=GMI1782 */1783 /* EXCLUDE (A*B, ) */1784 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_INT,1785 AMT_FILTER_FWD,1786 AMT_ACT_STATUS_FWD_NEW,1787 v6);1788 /* EXCLUDE (, B-A) */1789 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_SUB_REV,1790 AMT_FILTER_FWD,1791 AMT_ACT_STATUS_D_FWD_NEW,1792 v6);1793 /* (B-A)=0 */1794 amt_lookup_act_srcs(tunnel, gnode, zero_grec, AMT_OPS_UNI,1795 AMT_FILTER_D_FWD_NEW,1796 AMT_ACT_GMI_ZERO,1797 v6);1798 /* Group Timer=GMI */1799 if (!mod_delayed_work(amt_wq, &gnode->group_timer,1800 msecs_to_jiffies(amt_gmi(amt))))1801 dev_hold(amt->dev);1802 gnode->filter_mode = MCAST_EXCLUDE;1803 /* Delete (A-B) will be worked by amt_cleanup_srcs(). */1804 } else {1805/* Router State Report Rec'd New Router State Actions1806 * ------------ ------------ ---------------- -------1807 * EXCLUDE (X,Y) TO_EX (A) EXCLUDE (A-Y,Y*A) (A-X-Y)=Group Timer1808 * Delete (X-A)1809 * Delete (Y-A)1810 * Send Q(G,A-Y)1811 * Group Timer=GMI1812 */1813 /* Update (A-X-Y) as NONE/OLD */1814 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_SUB_REV,1815 AMT_FILTER_BOTH,1816 AMT_ACT_GT,1817 v6);1818 /* EXCLUDE (A-Y, ) */1819 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_SUB_REV,1820 AMT_FILTER_D_FWD,1821 AMT_ACT_STATUS_FWD_NEW,1822 v6);1823 /* EXCLUDE (, Y*A) */1824 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_INT,1825 AMT_FILTER_D_FWD,1826 AMT_ACT_STATUS_D_FWD_NEW,1827 v6);1828 /* Group Timer=GMI */1829 if (!mod_delayed_work(amt_wq, &gnode->group_timer,1830 msecs_to_jiffies(amt_gmi(amt))))1831 dev_hold(amt->dev);1832 /* Delete (X-A), (Y-A) will be worked by amt_cleanup_srcs(). */1833 }1834}1835 1836static void amt_mcast_allow_handler(struct amt_dev *amt,1837 struct amt_tunnel_list *tunnel,1838 struct amt_group_node *gnode,1839 void *grec, void *zero_grec, bool v6)1840{1841 if (gnode->filter_mode == MCAST_INCLUDE) {1842/* Router State Report Rec'd New Router State Actions1843 * ------------ ------------ ---------------- -------1844 * INCLUDE (A) ALLOW (B) INCLUDE (A+B) (B)=GMI1845 */1846 /* INCLUDE (A+B) */1847 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_UNI,1848 AMT_FILTER_FWD,1849 AMT_ACT_STATUS_FWD_NEW,1850 v6);1851 /* (B)=GMI */1852 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_INT,1853 AMT_FILTER_FWD_NEW,1854 AMT_ACT_GMI,1855 v6);1856 } else {1857/* Router State Report Rec'd New Router State Actions1858 * ------------ ------------ ---------------- -------1859 * EXCLUDE (X,Y) ALLOW (A) EXCLUDE (X+A,Y-A) (A)=GMI1860 */1861 /* EXCLUDE (X+A, ) */1862 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_UNI,1863 AMT_FILTER_FWD,1864 AMT_ACT_STATUS_FWD_NEW,1865 v6);1866 /* EXCLUDE (, Y-A) */1867 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_SUB,1868 AMT_FILTER_D_FWD,1869 AMT_ACT_STATUS_D_FWD_NEW,1870 v6);1871 /* (A)=GMI1872 * All (A) source are now FWD/NEW status.1873 */1874 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_INT,1875 AMT_FILTER_FWD_NEW,1876 AMT_ACT_GMI,1877 v6);1878 }1879}1880 1881static void amt_mcast_block_handler(struct amt_dev *amt,1882 struct amt_tunnel_list *tunnel,1883 struct amt_group_node *gnode,1884 void *grec, void *zero_grec, bool v6)1885{1886 if (gnode->filter_mode == MCAST_INCLUDE) {1887/* Router State Report Rec'd New Router State Actions1888 * ------------ ------------ ---------------- -------1889 * INCLUDE (A) BLOCK (B) INCLUDE (A) Send Q(G,A*B)1890 */1891 /* INCLUDE (A) */1892 amt_lookup_act_srcs(tunnel, gnode, zero_grec, AMT_OPS_UNI,1893 AMT_FILTER_FWD,1894 AMT_ACT_STATUS_FWD_NEW,1895 v6);1896 } else {1897/* Router State Report Rec'd New Router State Actions1898 * ------------ ------------ ---------------- -------1899 * EXCLUDE (X,Y) BLOCK (A) EXCLUDE (X+(A-Y),Y) (A-X-Y)=Group Timer1900 * Send Q(G,A-Y)1901 */1902 /* (A-X-Y)=Group Timer */1903 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_SUB_REV,1904 AMT_FILTER_BOTH,1905 AMT_ACT_GT,1906 v6);1907 /* EXCLUDE (X, ) */1908 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_UNI,1909 AMT_FILTER_FWD,1910 AMT_ACT_STATUS_FWD_NEW,1911 v6);1912 /* EXCLUDE (X+(A-Y) */1913 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_SUB_REV,1914 AMT_FILTER_D_FWD,1915 AMT_ACT_STATUS_FWD_NEW,1916 v6);1917 /* EXCLUDE (, Y) */1918 amt_lookup_act_srcs(tunnel, gnode, grec, AMT_OPS_UNI,1919 AMT_FILTER_D_FWD,1920 AMT_ACT_STATUS_D_FWD_NEW,1921 v6);1922 }1923}1924 1925/* RFC 33761926 * 7.3.2. In the Presence of Older Version Group Members1927 *1928 * When Group Compatibility Mode is IGMPv2, a router internally1929 * translates the following IGMPv2 messages for that group to their1930 * IGMPv3 equivalents:1931 *1932 * IGMPv2 Message IGMPv3 Equivalent1933 * -------------- -----------------1934 * Report IS_EX( {} )1935 * Leave TO_IN( {} )1936 */1937static void amt_igmpv2_report_handler(struct amt_dev *amt, struct sk_buff *skb,1938 struct amt_tunnel_list *tunnel)1939{1940 struct igmphdr *ih = igmp_hdr(skb);1941 struct iphdr *iph = ip_hdr(skb);1942 struct amt_group_node *gnode;1943 union amt_addr group, host;1944 1945 memset(&group, 0, sizeof(union amt_addr));1946 group.ip4 = ih->group;1947 memset(&host, 0, sizeof(union amt_addr));1948 host.ip4 = iph->saddr;1949 1950 gnode = amt_lookup_group(tunnel, &group, &host, false);1951 if (!gnode) {1952 gnode = amt_add_group(amt, tunnel, &group, &host, false);1953 if (!IS_ERR(gnode)) {1954 gnode->filter_mode = MCAST_EXCLUDE;1955 if (!mod_delayed_work(amt_wq, &gnode->group_timer,1956 msecs_to_jiffies(amt_gmi(amt))))1957 dev_hold(amt->dev);1958 }1959 }1960}1961 1962/* RFC 33761963 * 7.3.2. In the Presence of Older Version Group Members1964 *1965 * When Group Compatibility Mode is IGMPv2, a router internally1966 * translates the following IGMPv2 messages for that group to their1967 * IGMPv3 equivalents:1968 *1969 * IGMPv2 Message IGMPv3 Equivalent1970 * -------------- -----------------1971 * Report IS_EX( {} )1972 * Leave TO_IN( {} )1973 */1974static void amt_igmpv2_leave_handler(struct amt_dev *amt, struct sk_buff *skb,1975 struct amt_tunnel_list *tunnel)1976{1977 struct igmphdr *ih = igmp_hdr(skb);1978 struct iphdr *iph = ip_hdr(skb);1979 struct amt_group_node *gnode;1980 union amt_addr group, host;1981 1982 memset(&group, 0, sizeof(union amt_addr));1983 group.ip4 = ih->group;1984 memset(&host, 0, sizeof(union amt_addr));1985 host.ip4 = iph->saddr;1986 1987 gnode = amt_lookup_group(tunnel, &group, &host, false);1988 if (gnode)1989 amt_del_group(amt, gnode);1990}1991 1992static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb,1993 struct amt_tunnel_list *tunnel)1994{1995 struct igmpv3_report *ihrv3 = igmpv3_report_hdr(skb);1996 int len = skb_transport_offset(skb) + sizeof(*ihrv3);1997 void *zero_grec = (void *)&igmpv3_zero_grec;1998 struct iphdr *iph = ip_hdr(skb);1999 struct amt_group_node *gnode;2000 union amt_addr group, host;2001 struct igmpv3_grec *grec;2002 u16 nsrcs;2003 int i;2004 2005 for (i = 0; i < ntohs(ihrv3->ngrec); i++) {2006 len += sizeof(*grec);2007 if (!ip_mc_may_pull(skb, len))2008 break;2009 2010 grec = (void *)(skb->data + len - sizeof(*grec));2011 nsrcs = ntohs(grec->grec_nsrcs);2012 2013 len += nsrcs * sizeof(__be32);2014 if (!ip_mc_may_pull(skb, len))2015 break;2016 2017 memset(&group, 0, sizeof(union amt_addr));2018 group.ip4 = grec->grec_mca;2019 memset(&host, 0, sizeof(union amt_addr));2020 host.ip4 = iph->saddr;2021 gnode = amt_lookup_group(tunnel, &group, &host, false);2022 if (!gnode) {2023 gnode = amt_add_group(amt, tunnel, &group, &host,2024 false);2025 if (IS_ERR(gnode))2026 continue;2027 }2028 2029 amt_add_srcs(amt, tunnel, gnode, grec, false);2030 switch (grec->grec_type) {2031 case IGMPV3_MODE_IS_INCLUDE:2032 amt_mcast_is_in_handler(amt, tunnel, gnode, grec,2033 zero_grec, false);2034 break;2035 case IGMPV3_MODE_IS_EXCLUDE:2036 amt_mcast_is_ex_handler(amt, tunnel, gnode, grec,2037 zero_grec, false);2038 break;2039 case IGMPV3_CHANGE_TO_INCLUDE:2040 amt_mcast_to_in_handler(amt, tunnel, gnode, grec,2041 zero_grec, false);2042 break;2043 case IGMPV3_CHANGE_TO_EXCLUDE:2044 amt_mcast_to_ex_handler(amt, tunnel, gnode, grec,2045 zero_grec, false);2046 break;2047 case IGMPV3_ALLOW_NEW_SOURCES:2048 amt_mcast_allow_handler(amt, tunnel, gnode, grec,2049 zero_grec, false);2050 break;2051 case IGMPV3_BLOCK_OLD_SOURCES:2052 amt_mcast_block_handler(amt, tunnel, gnode, grec,2053 zero_grec, false);2054 break;2055 default:2056 break;2057 }2058 amt_cleanup_srcs(amt, tunnel, gnode);2059 }2060}2061 2062/* caller held tunnel->lock */2063static void amt_igmp_report_handler(struct amt_dev *amt, struct sk_buff *skb,2064 struct amt_tunnel_list *tunnel)2065{2066 struct igmphdr *ih = igmp_hdr(skb);2067 2068 switch (ih->type) {2069 case IGMPV3_HOST_MEMBERSHIP_REPORT:2070 amt_igmpv3_report_handler(amt, skb, tunnel);2071 break;2072 case IGMPV2_HOST_MEMBERSHIP_REPORT:2073 amt_igmpv2_report_handler(amt, skb, tunnel);2074 break;2075 case IGMP_HOST_LEAVE_MESSAGE:2076 amt_igmpv2_leave_handler(amt, skb, tunnel);2077 break;2078 default:2079 break;2080 }2081}2082 2083#if IS_ENABLED(CONFIG_IPV6)2084/* RFC 38102085 * 8.3.2. In the Presence of MLDv1 Multicast Address Listeners2086 *2087 * When Multicast Address Compatibility Mode is MLDv2, a router acts2088 * using the MLDv2 protocol for that multicast address. When Multicast2089 * Address Compatibility Mode is MLDv1, a router internally translates2090 * the following MLDv1 messages for that multicast address to their2091 * MLDv2 equivalents:2092 *2093 * MLDv1 Message MLDv2 Equivalent2094 * -------------- -----------------2095 * Report IS_EX( {} )2096 * Done TO_IN( {} )2097 */2098static void amt_mldv1_report_handler(struct amt_dev *amt, struct sk_buff *skb,2099 struct amt_tunnel_list *tunnel)2100{2101 struct mld_msg *mld = (struct mld_msg *)icmp6_hdr(skb);2102 struct ipv6hdr *ip6h = ipv6_hdr(skb);2103 struct amt_group_node *gnode;2104 union amt_addr group, host;2105 2106 memcpy(&group.ip6, &mld->mld_mca, sizeof(struct in6_addr));2107 memcpy(&host.ip6, &ip6h->saddr, sizeof(struct in6_addr));2108 2109 gnode = amt_lookup_group(tunnel, &group, &host, true);2110 if (!gnode) {2111 gnode = amt_add_group(amt, tunnel, &group, &host, true);2112 if (!IS_ERR(gnode)) {2113 gnode->filter_mode = MCAST_EXCLUDE;2114 if (!mod_delayed_work(amt_wq, &gnode->group_timer,2115 msecs_to_jiffies(amt_gmi(amt))))2116 dev_hold(amt->dev);2117 }2118 }2119}2120 2121/* RFC 38102122 * 8.3.2. In the Presence of MLDv1 Multicast Address Listeners2123 *2124 * When Multicast Address Compatibility Mode is MLDv2, a router acts2125 * using the MLDv2 protocol for that multicast address. When Multicast2126 * Address Compatibility Mode is MLDv1, a router internally translates2127 * the following MLDv1 messages for that multicast address to their2128 * MLDv2 equivalents:2129 *2130 * MLDv1 Message MLDv2 Equivalent2131 * -------------- -----------------2132 * Report IS_EX( {} )2133 * Done TO_IN( {} )2134 */2135static void amt_mldv1_leave_handler(struct amt_dev *amt, struct sk_buff *skb,2136 struct amt_tunnel_list *tunnel)2137{2138 struct mld_msg *mld = (struct mld_msg *)icmp6_hdr(skb);2139 struct iphdr *iph = ip_hdr(skb);2140 struct amt_group_node *gnode;2141 union amt_addr group, host;2142 2143 memcpy(&group.ip6, &mld->mld_mca, sizeof(struct in6_addr));2144 memset(&host, 0, sizeof(union amt_addr));2145 host.ip4 = iph->saddr;2146 2147 gnode = amt_lookup_group(tunnel, &group, &host, true);2148 if (gnode) {2149 amt_del_group(amt, gnode);2150 return;2151 }2152}2153 2154static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb,2155 struct amt_tunnel_list *tunnel)2156{2157 struct mld2_report *mld2r = (struct mld2_report *)icmp6_hdr(skb);2158 int len = skb_transport_offset(skb) + sizeof(*mld2r);2159 void *zero_grec = (void *)&mldv2_zero_grec;2160 struct ipv6hdr *ip6h = ipv6_hdr(skb);2161 struct amt_group_node *gnode;2162 union amt_addr group, host;2163 struct mld2_grec *grec;2164 u16 nsrcs;2165 int i;2166 2167 for (i = 0; i < ntohs(mld2r->mld2r_ngrec); i++) {2168 len += sizeof(*grec);2169 if (!ipv6_mc_may_pull(skb, len))2170 break;2171 2172 grec = (void *)(skb->data + len - sizeof(*grec));2173 nsrcs = ntohs(grec->grec_nsrcs);2174 2175 len += nsrcs * sizeof(struct in6_addr);2176 if (!ipv6_mc_may_pull(skb, len))2177 break;2178 2179 memset(&group, 0, sizeof(union amt_addr));2180 group.ip6 = grec->grec_mca;2181 memset(&host, 0, sizeof(union amt_addr));2182 host.ip6 = ip6h->saddr;2183 gnode = amt_lookup_group(tunnel, &group, &host, true);2184 if (!gnode) {2185 gnode = amt_add_group(amt, tunnel, &group, &host,2186 ETH_P_IPV6);2187 if (IS_ERR(gnode))2188 continue;2189 }2190 2191 amt_add_srcs(amt, tunnel, gnode, grec, true);2192 switch (grec->grec_type) {2193 case MLD2_MODE_IS_INCLUDE:2194 amt_mcast_is_in_handler(amt, tunnel, gnode, grec,2195 zero_grec, true);2196 break;2197 case MLD2_MODE_IS_EXCLUDE:2198 amt_mcast_is_ex_handler(amt, tunnel, gnode, grec,2199 zero_grec, true);2200 break;2201 case MLD2_CHANGE_TO_INCLUDE:2202 amt_mcast_to_in_handler(amt, tunnel, gnode, grec,2203 zero_grec, true);2204 break;2205 case MLD2_CHANGE_TO_EXCLUDE:2206 amt_mcast_to_ex_handler(amt, tunnel, gnode, grec,2207 zero_grec, true);2208 break;2209 case MLD2_ALLOW_NEW_SOURCES:2210 amt_mcast_allow_handler(amt, tunnel, gnode, grec,2211 zero_grec, true);2212 break;2213 case MLD2_BLOCK_OLD_SOURCES:2214 amt_mcast_block_handler(amt, tunnel, gnode, grec,2215 zero_grec, true);2216 break;2217 default:2218 break;2219 }2220 amt_cleanup_srcs(amt, tunnel, gnode);2221 }2222}2223 2224/* caller held tunnel->lock */2225static void amt_mld_report_handler(struct amt_dev *amt, struct sk_buff *skb,2226 struct amt_tunnel_list *tunnel)2227{2228 struct mld_msg *mld = (struct mld_msg *)icmp6_hdr(skb);2229 2230 switch (mld->mld_type) {2231 case ICMPV6_MGM_REPORT:2232 amt_mldv1_report_handler(amt, skb, tunnel);2233 break;2234 case ICMPV6_MLD2_REPORT:2235 amt_mldv2_report_handler(amt, skb, tunnel);2236 break;2237 case ICMPV6_MGM_REDUCTION:2238 amt_mldv1_leave_handler(amt, skb, tunnel);2239 break;2240 default:2241 break;2242 }2243}2244#endif2245 2246static bool amt_advertisement_handler(struct amt_dev *amt, struct sk_buff *skb)2247{2248 struct amt_header_advertisement *amta;2249 int hdr_size;2250 2251 hdr_size = sizeof(*amta) + sizeof(struct udphdr);2252 if (!pskb_may_pull(skb, hdr_size))2253 return true;2254 2255 amta = (struct amt_header_advertisement *)(udp_hdr(skb) + 1);2256 if (!amta->ip4)2257 return true;2258 2259 if (amta->reserved || amta->version)2260 return true;2261 2262 if (ipv4_is_loopback(amta->ip4) || ipv4_is_multicast(amta->ip4) ||2263 ipv4_is_zeronet(amta->ip4))2264 return true;2265 2266 if (amt->status != AMT_STATUS_SENT_DISCOVERY ||2267 amt->nonce != amta->nonce)2268 return true;2269 2270 amt->remote_ip = amta->ip4;2271 netdev_dbg(amt->dev, "advertised remote ip = %pI4\n", &amt->remote_ip);2272 mod_delayed_work(amt_wq, &amt->req_wq, 0);2273 2274 amt_update_gw_status(amt, AMT_STATUS_RECEIVED_ADVERTISEMENT, true);2275 return false;2276}2277 2278static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)2279{2280 struct amt_header_mcast_data *amtmd;2281 int hdr_size, len, err;2282 struct ethhdr *eth;2283 struct iphdr *iph;2284 2285 if (READ_ONCE(amt->status) != AMT_STATUS_SENT_UPDATE)2286 return true;2287 2288 hdr_size = sizeof(*amtmd) + sizeof(struct udphdr);2289 if (!pskb_may_pull(skb, hdr_size))2290 return true;2291 2292 amtmd = (struct amt_header_mcast_data *)(udp_hdr(skb) + 1);2293 if (amtmd->reserved || amtmd->version)2294 return true;2295 2296 if (iptunnel_pull_header(skb, hdr_size, htons(ETH_P_IP), false))2297 return true;2298 2299 skb_reset_network_header(skb);2300 skb_push(skb, sizeof(*eth));2301 skb_reset_mac_header(skb);2302 skb_pull(skb, sizeof(*eth));2303 eth = eth_hdr(skb);2304 2305 if (!pskb_may_pull(skb, sizeof(*iph)))2306 return true;2307 iph = ip_hdr(skb);2308 2309 if (iph->version == 4) {2310 if (!ipv4_is_multicast(iph->daddr))2311 return true;2312 skb->protocol = htons(ETH_P_IP);2313 eth->h_proto = htons(ETH_P_IP);2314 ip_eth_mc_map(iph->daddr, eth->h_dest);2315#if IS_ENABLED(CONFIG_IPV6)2316 } else if (iph->version == 6) {2317 struct ipv6hdr *ip6h;2318 2319 if (!pskb_may_pull(skb, sizeof(*ip6h)))2320 return true;2321 2322 ip6h = ipv6_hdr(skb);2323 if (!ipv6_addr_is_multicast(&ip6h->daddr))2324 return true;2325 skb->protocol = htons(ETH_P_IPV6);2326 eth->h_proto = htons(ETH_P_IPV6);2327 ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);2328#endif2329 } else {2330 return true;2331 }2332 2333 skb->pkt_type = PACKET_MULTICAST;2334 skb->ip_summed = CHECKSUM_NONE;2335 len = skb->len;2336 err = gro_cells_receive(&amt->gro_cells, skb);2337 if (likely(err == NET_RX_SUCCESS))2338 dev_sw_netstats_rx_add(amt->dev, len);2339 else2340 amt->dev->stats.rx_dropped++;2341 2342 return false;2343}2344 2345static bool amt_membership_query_handler(struct amt_dev *amt,2346 struct sk_buff *skb)2347{2348 struct amt_header_membership_query *amtmq;2349 struct igmpv3_query *ihv3;2350 struct ethhdr *eth, *oeth;2351 struct iphdr *iph;2352 int hdr_size, len;2353 2354 hdr_size = sizeof(*amtmq) + sizeof(struct udphdr);2355 if (!pskb_may_pull(skb, hdr_size))2356 return true;2357 2358 amtmq = (struct amt_header_membership_query *)(udp_hdr(skb) + 1);2359 if (amtmq->reserved || amtmq->version)2360 return true;2361 2362 if (amtmq->nonce != amt->nonce)2363 return true;2364 2365 hdr_size -= sizeof(*eth);2366 if (iptunnel_pull_header(skb, hdr_size, htons(ETH_P_TEB), false))2367 return true;2368 2369 oeth = eth_hdr(skb);2370 skb_reset_mac_header(skb);2371 skb_pull(skb, sizeof(*eth));2372 skb_reset_network_header(skb);2373 eth = eth_hdr(skb);2374 if (!pskb_may_pull(skb, sizeof(*iph)))2375 return true;2376 2377 iph = ip_hdr(skb);2378 if (iph->version == 4) {2379 if (READ_ONCE(amt->ready4))2380 return true;2381 2382 if (!pskb_may_pull(skb, sizeof(*iph) + AMT_IPHDR_OPTS +2383 sizeof(*ihv3)))2384 return true;2385 2386 if (!ipv4_is_multicast(iph->daddr))2387 return true;2388 2389 ihv3 = skb_pull(skb, sizeof(*iph) + AMT_IPHDR_OPTS);2390 skb_reset_transport_header(skb);2391 skb_push(skb, sizeof(*iph) + AMT_IPHDR_OPTS);2392 WRITE_ONCE(amt->ready4, true);2393 amt->mac = amtmq->response_mac;2394 amt->req_cnt = 0;2395 amt->qi = ihv3->qqic;2396 skb->protocol = htons(ETH_P_IP);2397 eth->h_proto = htons(ETH_P_IP);2398 ip_eth_mc_map(iph->daddr, eth->h_dest);2399#if IS_ENABLED(CONFIG_IPV6)2400 } else if (iph->version == 6) {2401 struct mld2_query *mld2q;2402 struct ipv6hdr *ip6h;2403 2404 if (READ_ONCE(amt->ready6))2405 return true;2406 2407 if (!pskb_may_pull(skb, sizeof(*ip6h) + AMT_IP6HDR_OPTS +2408 sizeof(*mld2q)))2409 return true;2410 2411 ip6h = ipv6_hdr(skb);2412 if (!ipv6_addr_is_multicast(&ip6h->daddr))2413 return true;2414 2415 mld2q = skb_pull(skb, sizeof(*ip6h) + AMT_IP6HDR_OPTS);2416 skb_reset_transport_header(skb);2417 skb_push(skb, sizeof(*ip6h) + AMT_IP6HDR_OPTS);2418 WRITE_ONCE(amt->ready6, true);2419 amt->mac = amtmq->response_mac;2420 amt->req_cnt = 0;2421 amt->qi = mld2q->mld2q_qqic;2422 skb->protocol = htons(ETH_P_IPV6);2423 eth->h_proto = htons(ETH_P_IPV6);2424 ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);2425#endif2426 } else {2427 return true;2428 }2429 2430 ether_addr_copy(eth->h_source, oeth->h_source);2431 skb->pkt_type = PACKET_MULTICAST;2432 skb->ip_summed = CHECKSUM_NONE;2433 len = skb->len;2434 local_bh_disable();2435 if (__netif_rx(skb) == NET_RX_SUCCESS) {2436 amt_update_gw_status(amt, AMT_STATUS_RECEIVED_QUERY, true);2437 dev_sw_netstats_rx_add(amt->dev, len);2438 } else {2439 amt->dev->stats.rx_dropped++;2440 }2441 local_bh_enable();2442 2443 return false;2444}2445 2446static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)2447{2448 struct amt_header_membership_update *amtmu;2449 struct amt_tunnel_list *tunnel;2450 struct ethhdr *eth;2451 struct iphdr *iph;2452 int len, hdr_size;2453 2454 iph = ip_hdr(skb);2455 2456 hdr_size = sizeof(*amtmu) + sizeof(struct udphdr);2457 if (!pskb_may_pull(skb, hdr_size))2458 return true;2459 2460 amtmu = (struct amt_header_membership_update *)(udp_hdr(skb) + 1);2461 if (amtmu->reserved || amtmu->version)2462 return true;2463 2464 if (iptunnel_pull_header(skb, hdr_size, skb->protocol, false))2465 return true;2466 2467 skb_reset_network_header(skb);2468 2469 list_for_each_entry_rcu(tunnel, &amt->tunnel_list, list) {2470 if (tunnel->ip4 == iph->saddr) {2471 if ((amtmu->nonce == tunnel->nonce &&2472 amtmu->response_mac == tunnel->mac)) {2473 mod_delayed_work(amt_wq, &tunnel->gc_wq,2474 msecs_to_jiffies(amt_gmi(amt))2475 * 3);2476 goto report;2477 } else {2478 netdev_dbg(amt->dev, "Invalid MAC\n");2479 return true;2480 }2481 }2482 }2483 2484 return true;2485 2486report:2487 if (!pskb_may_pull(skb, sizeof(*iph)))2488 return true;2489 2490 iph = ip_hdr(skb);2491 if (iph->version == 4) {2492 if (ip_mc_check_igmp(skb)) {2493 netdev_dbg(amt->dev, "Invalid IGMP\n");2494 return true;2495 }2496 2497 spin_lock_bh(&tunnel->lock);2498 amt_igmp_report_handler(amt, skb, tunnel);2499 spin_unlock_bh(&tunnel->lock);2500 2501 skb_push(skb, sizeof(struct ethhdr));2502 skb_reset_mac_header(skb);2503 eth = eth_hdr(skb);2504 skb->protocol = htons(ETH_P_IP);2505 eth->h_proto = htons(ETH_P_IP);2506 ip_eth_mc_map(iph->daddr, eth->h_dest);2507#if IS_ENABLED(CONFIG_IPV6)2508 } else if (iph->version == 6) {2509 struct ipv6hdr *ip6h = ipv6_hdr(skb);2510 2511 if (ipv6_mc_check_mld(skb)) {2512 netdev_dbg(amt->dev, "Invalid MLD\n");2513 return true;2514 }2515 2516 spin_lock_bh(&tunnel->lock);2517 amt_mld_report_handler(amt, skb, tunnel);2518 spin_unlock_bh(&tunnel->lock);2519 2520 skb_push(skb, sizeof(struct ethhdr));2521 skb_reset_mac_header(skb);2522 eth = eth_hdr(skb);2523 skb->protocol = htons(ETH_P_IPV6);2524 eth->h_proto = htons(ETH_P_IPV6);2525 ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);2526#endif2527 } else {2528 netdev_dbg(amt->dev, "Unsupported Protocol\n");2529 return true;2530 }2531 2532 skb_pull(skb, sizeof(struct ethhdr));2533 skb->pkt_type = PACKET_MULTICAST;2534 skb->ip_summed = CHECKSUM_NONE;2535 len = skb->len;2536 if (__netif_rx(skb) == NET_RX_SUCCESS) {2537 amt_update_relay_status(tunnel, AMT_STATUS_RECEIVED_UPDATE,2538 true);2539 dev_sw_netstats_rx_add(amt->dev, len);2540 } else {2541 amt->dev->stats.rx_dropped++;2542 }2543 2544 return false;2545}2546 2547static void amt_send_advertisement(struct amt_dev *amt, __be32 nonce,2548 __be32 daddr, __be16 dport)2549{2550 struct amt_header_advertisement *amta;2551 int hlen, tlen, offset;2552 struct socket *sock;2553 struct udphdr *udph;2554 struct sk_buff *skb;2555 struct iphdr *iph;2556 struct rtable *rt;2557 struct flowi4 fl4;2558 u32 len;2559 int err;2560 2561 rcu_read_lock();2562 sock = rcu_dereference(amt->sock);2563 if (!sock)2564 goto out;2565 2566 if (!netif_running(amt->stream_dev) || !netif_running(amt->dev))2567 goto out;2568 2569 rt = ip_route_output_ports(amt->net, &fl4, sock->sk,2570 daddr, amt->local_ip,2571 dport, amt->relay_port,2572 IPPROTO_UDP, 0,2573 amt->stream_dev->ifindex);2574 if (IS_ERR(rt)) {2575 amt->dev->stats.tx_errors++;2576 goto out;2577 }2578 2579 hlen = LL_RESERVED_SPACE(amt->dev);2580 tlen = amt->dev->needed_tailroom;2581 len = hlen + tlen + sizeof(*iph) + sizeof(*udph) + sizeof(*amta);2582 skb = netdev_alloc_skb_ip_align(amt->dev, len);2583 if (!skb) {2584 ip_rt_put(rt);2585 amt->dev->stats.tx_errors++;2586 goto out;2587 }2588 2589 skb->priority = TC_PRIO_CONTROL;2590 skb_dst_set(skb, &rt->dst);2591 2592 len = sizeof(*iph) + sizeof(*udph) + sizeof(*amta);2593 skb_reset_network_header(skb);2594 skb_put(skb, len);2595 amta = skb_pull(skb, sizeof(*iph) + sizeof(*udph));2596 amta->version = 0;2597 amta->type = AMT_MSG_ADVERTISEMENT;2598 amta->reserved = 0;2599 amta->nonce = nonce;2600 amta->ip4 = amt->local_ip;2601 skb_push(skb, sizeof(*udph));2602 skb_reset_transport_header(skb);2603 udph = udp_hdr(skb);2604 udph->source = amt->relay_port;2605 udph->dest = dport;2606 udph->len = htons(sizeof(*amta) + sizeof(*udph));2607 udph->check = 0;2608 offset = skb_transport_offset(skb);2609 skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);2610 udph->check = csum_tcpudp_magic(amt->local_ip, daddr,2611 sizeof(*udph) + sizeof(*amta),2612 IPPROTO_UDP, skb->csum);2613 2614 skb_push(skb, sizeof(*iph));2615 iph = ip_hdr(skb);2616 iph->version = 4;2617 iph->ihl = (sizeof(struct iphdr)) >> 2;2618 iph->tos = AMT_TOS;2619 iph->frag_off = 0;2620 iph->ttl = ip4_dst_hoplimit(&rt->dst);2621 iph->daddr = daddr;2622 iph->saddr = amt->local_ip;2623 iph->protocol = IPPROTO_UDP;2624 iph->tot_len = htons(len);2625 2626 skb->ip_summed = CHECKSUM_NONE;2627 ip_select_ident(amt->net, skb, NULL);2628 ip_send_check(iph);2629 err = ip_local_out(amt->net, sock->sk, skb);2630 if (unlikely(net_xmit_eval(err)))2631 amt->dev->stats.tx_errors++;2632 2633out:2634 rcu_read_unlock();2635}2636 2637static bool amt_discovery_handler(struct amt_dev *amt, struct sk_buff *skb)2638{2639 struct amt_header_discovery *amtd;2640 struct udphdr *udph;2641 struct iphdr *iph;2642 2643 if (!pskb_may_pull(skb, sizeof(*udph) + sizeof(*amtd)))2644 return true;2645 2646 iph = ip_hdr(skb);2647 udph = udp_hdr(skb);2648 amtd = (struct amt_header_discovery *)(udp_hdr(skb) + 1);2649 2650 if (amtd->reserved || amtd->version)2651 return true;2652 2653 amt_send_advertisement(amt, amtd->nonce, iph->saddr, udph->source);2654 2655 return false;2656}2657 2658static bool amt_request_handler(struct amt_dev *amt, struct sk_buff *skb)2659{2660 struct amt_header_request *amtrh;2661 struct amt_tunnel_list *tunnel;2662 unsigned long long key;2663 struct udphdr *udph;2664 struct iphdr *iph;2665 u64 mac;2666 int i;2667 2668 if (!pskb_may_pull(skb, sizeof(*udph) + sizeof(*amtrh)))2669 return true;2670 2671 iph = ip_hdr(skb);2672 udph = udp_hdr(skb);2673 amtrh = (struct amt_header_request *)(udp_hdr(skb) + 1);2674 2675 if (amtrh->reserved1 || amtrh->reserved2 || amtrh->version)2676 return true;2677 2678 list_for_each_entry_rcu(tunnel, &amt->tunnel_list, list)2679 if (tunnel->ip4 == iph->saddr)2680 goto send;2681 2682 spin_lock_bh(&amt->lock);2683 if (amt->nr_tunnels >= amt->max_tunnels) {2684 spin_unlock_bh(&amt->lock);2685 icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);2686 return true;2687 }2688 2689 tunnel = kzalloc(sizeof(*tunnel) +2690 (sizeof(struct hlist_head) * amt->hash_buckets),2691 GFP_ATOMIC);2692 if (!tunnel) {2693 spin_unlock_bh(&amt->lock);2694 return true;2695 }2696 2697 tunnel->source_port = udph->source;2698 tunnel->ip4 = iph->saddr;2699 2700 memcpy(&key, &tunnel->key, sizeof(unsigned long long));2701 tunnel->amt = amt;2702 spin_lock_init(&tunnel->lock);2703 for (i = 0; i < amt->hash_buckets; i++)2704 INIT_HLIST_HEAD(&tunnel->groups[i]);2705 2706 INIT_DELAYED_WORK(&tunnel->gc_wq, amt_tunnel_expire);2707 2708 list_add_tail_rcu(&tunnel->list, &amt->tunnel_list);2709 tunnel->key = amt->key;2710 __amt_update_relay_status(tunnel, AMT_STATUS_RECEIVED_REQUEST, true);2711 amt->nr_tunnels++;2712 mod_delayed_work(amt_wq, &tunnel->gc_wq,2713 msecs_to_jiffies(amt_gmi(amt)));2714 spin_unlock_bh(&amt->lock);2715 2716send:2717 tunnel->nonce = amtrh->nonce;2718 mac = siphash_3u32((__force u32)tunnel->ip4,2719 (__force u32)tunnel->source_port,2720 (__force u32)tunnel->nonce,2721 &tunnel->key);2722 tunnel->mac = mac >> 16;2723 2724 if (!netif_running(amt->dev) || !netif_running(amt->stream_dev))2725 return true;2726 2727 if (!amtrh->p)2728 amt_send_igmp_gq(amt, tunnel);2729 else2730 amt_send_mld_gq(amt, tunnel);2731 2732 return false;2733}2734 2735static void amt_gw_rcv(struct amt_dev *amt, struct sk_buff *skb)2736{2737 int type = amt_parse_type(skb);2738 int err = 1;2739 2740 if (type == -1)2741 goto drop;2742 2743 if (amt->mode == AMT_MODE_GATEWAY) {2744 switch (type) {2745 case AMT_MSG_ADVERTISEMENT:2746 err = amt_advertisement_handler(amt, skb);2747 break;2748 case AMT_MSG_MEMBERSHIP_QUERY:2749 err = amt_membership_query_handler(amt, skb);2750 if (!err)2751 return;2752 break;2753 default:2754 netdev_dbg(amt->dev, "Invalid type of Gateway\n");2755 break;2756 }2757 }2758drop:2759 if (err) {2760 amt->dev->stats.rx_dropped++;2761 kfree_skb(skb);2762 } else {2763 consume_skb(skb);2764 }2765}2766 2767static int amt_rcv(struct sock *sk, struct sk_buff *skb)2768{2769 struct amt_dev *amt;2770 struct iphdr *iph;2771 int type;2772 bool err;2773 2774 rcu_read_lock_bh();2775 amt = rcu_dereference_sk_user_data(sk);2776 if (!amt) {2777 err = true;2778 kfree_skb(skb);2779 goto out;2780 }2781 2782 skb->dev = amt->dev;2783 iph = ip_hdr(skb);2784 type = amt_parse_type(skb);2785 if (type == -1) {2786 err = true;2787 goto drop;2788 }2789 2790 if (amt->mode == AMT_MODE_GATEWAY) {2791 switch (type) {2792 case AMT_MSG_ADVERTISEMENT:2793 if (iph->saddr != amt->discovery_ip) {2794 netdev_dbg(amt->dev, "Invalid Relay IP\n");2795 err = true;2796 goto drop;2797 }2798 if (amt_queue_event(amt, AMT_EVENT_RECEIVE, skb)) {2799 netdev_dbg(amt->dev, "AMT Event queue full\n");2800 err = true;2801 goto drop;2802 }2803 goto out;2804 case AMT_MSG_MULTICAST_DATA:2805 if (iph->saddr != amt->remote_ip) {2806 netdev_dbg(amt->dev, "Invalid Relay IP\n");2807 err = true;2808 goto drop;2809 }2810 err = amt_multicast_data_handler(amt, skb);2811 if (err)2812 goto drop;2813 else2814 goto out;2815 case AMT_MSG_MEMBERSHIP_QUERY:2816 if (iph->saddr != amt->remote_ip) {2817 netdev_dbg(amt->dev, "Invalid Relay IP\n");2818 err = true;2819 goto drop;2820 }2821 if (amt_queue_event(amt, AMT_EVENT_RECEIVE, skb)) {2822 netdev_dbg(amt->dev, "AMT Event queue full\n");2823 err = true;2824 goto drop;2825 }2826 goto out;2827 default:2828 err = true;2829 netdev_dbg(amt->dev, "Invalid type of Gateway\n");2830 break;2831 }2832 } else {2833 switch (type) {2834 case AMT_MSG_DISCOVERY:2835 err = amt_discovery_handler(amt, skb);2836 break;2837 case AMT_MSG_REQUEST:2838 err = amt_request_handler(amt, skb);2839 break;2840 case AMT_MSG_MEMBERSHIP_UPDATE:2841 err = amt_update_handler(amt, skb);2842 if (err)2843 goto drop;2844 else2845 goto out;2846 default:2847 err = true;2848 netdev_dbg(amt->dev, "Invalid type of relay\n");2849 break;2850 }2851 }2852drop:2853 if (err) {2854 amt->dev->stats.rx_dropped++;2855 kfree_skb(skb);2856 } else {2857 consume_skb(skb);2858 }2859out:2860 rcu_read_unlock_bh();2861 return 0;2862}2863 2864static void amt_event_work(struct work_struct *work)2865{2866 struct amt_dev *amt = container_of(work, struct amt_dev, event_wq);2867 struct sk_buff *skb;2868 u8 event;2869 int i;2870 2871 for (i = 0; i < AMT_MAX_EVENTS; i++) {2872 spin_lock_bh(&amt->lock);2873 if (amt->nr_events == 0) {2874 spin_unlock_bh(&amt->lock);2875 return;2876 }2877 event = amt->events[amt->event_idx].event;2878 skb = amt->events[amt->event_idx].skb;2879 amt->events[amt->event_idx].event = AMT_EVENT_NONE;2880 amt->events[amt->event_idx].skb = NULL;2881 amt->nr_events--;2882 amt->event_idx++;2883 amt->event_idx %= AMT_MAX_EVENTS;2884 spin_unlock_bh(&amt->lock);2885 2886 switch (event) {2887 case AMT_EVENT_RECEIVE:2888 amt_gw_rcv(amt, skb);2889 break;2890 case AMT_EVENT_SEND_DISCOVERY:2891 amt_event_send_discovery(amt);2892 break;2893 case AMT_EVENT_SEND_REQUEST:2894 amt_event_send_request(amt);2895 break;2896 default:2897 kfree_skb(skb);2898 break;2899 }2900 }2901}2902 2903static int amt_err_lookup(struct sock *sk, struct sk_buff *skb)2904{2905 struct amt_dev *amt;2906 int type;2907 2908 rcu_read_lock_bh();2909 amt = rcu_dereference_sk_user_data(sk);2910 if (!amt)2911 goto out;2912 2913 if (amt->mode != AMT_MODE_GATEWAY)2914 goto drop;2915 2916 type = amt_parse_type(skb);2917 if (type == -1)2918 goto drop;2919 2920 netdev_dbg(amt->dev, "Received IGMP Unreachable of %s\n",2921 type_str[type]);2922 switch (type) {2923 case AMT_MSG_DISCOVERY:2924 break;2925 case AMT_MSG_REQUEST:2926 case AMT_MSG_MEMBERSHIP_UPDATE:2927 if (READ_ONCE(amt->status) >= AMT_STATUS_RECEIVED_ADVERTISEMENT)2928 mod_delayed_work(amt_wq, &amt->req_wq, 0);2929 break;2930 default:2931 goto drop;2932 }2933out:2934 rcu_read_unlock_bh();2935 return 0;2936drop:2937 rcu_read_unlock_bh();2938 amt->dev->stats.rx_dropped++;2939 return 0;2940}2941 2942static struct socket *amt_create_sock(struct net *net, __be16 port)2943{2944 struct udp_port_cfg udp_conf;2945 struct socket *sock;2946 int err;2947 2948 memset(&udp_conf, 0, sizeof(udp_conf));2949 udp_conf.family = AF_INET;2950 udp_conf.local_ip.s_addr = htonl(INADDR_ANY);2951 2952 udp_conf.local_udp_port = port;2953 2954 err = udp_sock_create(net, &udp_conf, &sock);2955 if (err < 0)2956 return ERR_PTR(err);2957 2958 return sock;2959}2960 2961static int amt_socket_create(struct amt_dev *amt)2962{2963 struct udp_tunnel_sock_cfg tunnel_cfg;2964 struct socket *sock;2965 2966 sock = amt_create_sock(amt->net, amt->relay_port);2967 if (IS_ERR(sock))2968 return PTR_ERR(sock);2969 2970 /* Mark socket as an encapsulation socket */2971 memset(&tunnel_cfg, 0, sizeof(tunnel_cfg));2972 tunnel_cfg.sk_user_data = amt;2973 tunnel_cfg.encap_type = 1;2974 tunnel_cfg.encap_rcv = amt_rcv;2975 tunnel_cfg.encap_err_lookup = amt_err_lookup;2976 tunnel_cfg.encap_destroy = NULL;2977 setup_udp_tunnel_sock(amt->net, sock, &tunnel_cfg);2978 2979 rcu_assign_pointer(amt->sock, sock);2980 return 0;2981}2982 2983static int amt_dev_open(struct net_device *dev)2984{2985 struct amt_dev *amt = netdev_priv(dev);2986 int err;2987 2988 amt->ready4 = false;2989 amt->ready6 = false;2990 amt->event_idx = 0;2991 amt->nr_events = 0;2992 2993 err = amt_socket_create(amt);2994 if (err)2995 return err;2996 2997 amt->req_cnt = 0;2998 amt->remote_ip = 0;2999 amt->nonce = 0;3000 get_random_bytes(&amt->key, sizeof(siphash_key_t));3001 3002 amt->status = AMT_STATUS_INIT;3003 if (amt->mode == AMT_MODE_GATEWAY) {3004 mod_delayed_work(amt_wq, &amt->discovery_wq, 0);3005 mod_delayed_work(amt_wq, &amt->req_wq, 0);3006 } else if (amt->mode == AMT_MODE_RELAY) {3007 mod_delayed_work(amt_wq, &amt->secret_wq,3008 msecs_to_jiffies(AMT_SECRET_TIMEOUT));3009 }3010 return err;3011}3012 3013static int amt_dev_stop(struct net_device *dev)3014{3015 struct amt_dev *amt = netdev_priv(dev);3016 struct amt_tunnel_list *tunnel, *tmp;3017 struct socket *sock;3018 struct sk_buff *skb;3019 int i;3020 3021 cancel_delayed_work_sync(&amt->req_wq);3022 cancel_delayed_work_sync(&amt->discovery_wq);3023 cancel_delayed_work_sync(&amt->secret_wq);3024 3025 /* shutdown */3026 sock = rtnl_dereference(amt->sock);3027 RCU_INIT_POINTER(amt->sock, NULL);3028 synchronize_net();3029 if (sock)3030 udp_tunnel_sock_release(sock);3031 3032 cancel_work_sync(&amt->event_wq);3033 for (i = 0; i < AMT_MAX_EVENTS; i++) {3034 skb = amt->events[i].skb;3035 kfree_skb(skb);3036 amt->events[i].event = AMT_EVENT_NONE;3037 amt->events[i].skb = NULL;3038 }3039 3040 amt->ready4 = false;3041 amt->ready6 = false;3042 amt->req_cnt = 0;3043 amt->remote_ip = 0;3044 3045 list_for_each_entry_safe(tunnel, tmp, &amt->tunnel_list, list) {3046 list_del_rcu(&tunnel->list);3047 amt->nr_tunnels--;3048 cancel_delayed_work_sync(&tunnel->gc_wq);3049 amt_clear_groups(tunnel);3050 kfree_rcu(tunnel, rcu);3051 }3052 3053 return 0;3054}3055 3056static const struct device_type amt_type = {3057 .name = "amt",3058};3059 3060static int amt_dev_init(struct net_device *dev)3061{3062 struct amt_dev *amt = netdev_priv(dev);3063 int err;3064 3065 amt->dev = dev;3066 3067 err = gro_cells_init(&amt->gro_cells, dev);3068 if (err)3069 return err;3070 3071 return 0;3072}3073 3074static void amt_dev_uninit(struct net_device *dev)3075{3076 struct amt_dev *amt = netdev_priv(dev);3077 3078 gro_cells_destroy(&amt->gro_cells);3079}3080 3081static const struct net_device_ops amt_netdev_ops = {3082 .ndo_init = amt_dev_init,3083 .ndo_uninit = amt_dev_uninit,3084 .ndo_open = amt_dev_open,3085 .ndo_stop = amt_dev_stop,3086 .ndo_start_xmit = amt_dev_xmit,3087};3088 3089static void amt_link_setup(struct net_device *dev)3090{3091 dev->netdev_ops = &amt_netdev_ops;3092 dev->needs_free_netdev = true;3093 SET_NETDEV_DEVTYPE(dev, &amt_type);3094 dev->min_mtu = ETH_MIN_MTU;3095 dev->max_mtu = ETH_MAX_MTU;3096 dev->type = ARPHRD_NONE;3097 dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;3098 dev->hard_header_len = 0;3099 dev->addr_len = 0;3100 dev->priv_flags |= IFF_NO_QUEUE;3101 dev->lltx = true;3102 dev->netns_local = true;3103 dev->features |= NETIF_F_GSO_SOFTWARE;3104 dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM;3105 dev->hw_features |= NETIF_F_FRAGLIST | NETIF_F_RXCSUM;3106 dev->hw_features |= NETIF_F_GSO_SOFTWARE;3107 dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;3108 eth_hw_addr_random(dev);3109 eth_zero_addr(dev->broadcast);3110 ether_setup(dev);3111}3112 3113static const struct nla_policy amt_policy[IFLA_AMT_MAX + 1] = {3114 [IFLA_AMT_MODE] = { .type = NLA_U32 },3115 [IFLA_AMT_RELAY_PORT] = { .type = NLA_U16 },3116 [IFLA_AMT_GATEWAY_PORT] = { .type = NLA_U16 },3117 [IFLA_AMT_LINK] = { .type = NLA_U32 },3118 [IFLA_AMT_LOCAL_IP] = { .len = sizeof_field(struct iphdr, daddr) },3119 [IFLA_AMT_REMOTE_IP] = { .len = sizeof_field(struct iphdr, daddr) },3120 [IFLA_AMT_DISCOVERY_IP] = { .len = sizeof_field(struct iphdr, daddr) },3121 [IFLA_AMT_MAX_TUNNELS] = { .type = NLA_U32 },3122};3123 3124static int amt_validate(struct nlattr *tb[], struct nlattr *data[],3125 struct netlink_ext_ack *extack)3126{3127 if (!data)3128 return -EINVAL;3129 3130 if (!data[IFLA_AMT_LINK]) {3131 NL_SET_ERR_MSG_ATTR(extack, data[IFLA_AMT_LINK],3132 "Link attribute is required");3133 return -EINVAL;3134 }3135 3136 if (!data[IFLA_AMT_MODE]) {3137 NL_SET_ERR_MSG_ATTR(extack, data[IFLA_AMT_MODE],3138 "Mode attribute is required");3139 return -EINVAL;3140 }3141 3142 if (nla_get_u32(data[IFLA_AMT_MODE]) > AMT_MODE_MAX) {3143 NL_SET_ERR_MSG_ATTR(extack, data[IFLA_AMT_MODE],3144 "Mode attribute is not valid");3145 return -EINVAL;3146 }3147 3148 if (!data[IFLA_AMT_LOCAL_IP]) {3149 NL_SET_ERR_MSG_ATTR(extack, data[IFLA_AMT_DISCOVERY_IP],3150 "Local attribute is required");3151 return -EINVAL;3152 }3153 3154 if (!data[IFLA_AMT_DISCOVERY_IP] &&3155 nla_get_u32(data[IFLA_AMT_MODE]) == AMT_MODE_GATEWAY) {3156 NL_SET_ERR_MSG_ATTR(extack, data[IFLA_AMT_LOCAL_IP],3157 "Discovery attribute is required");3158 return -EINVAL;3159 }3160 3161 return 0;3162}3163 3164static int amt_newlink(struct net *net, struct net_device *dev,3165 struct nlattr *tb[], struct nlattr *data[],3166 struct netlink_ext_ack *extack)3167{3168 struct amt_dev *amt = netdev_priv(dev);3169 int err = -EINVAL;3170 3171 amt->net = net;3172 amt->mode = nla_get_u32(data[IFLA_AMT_MODE]);3173 3174 if (data[IFLA_AMT_MAX_TUNNELS] &&3175 nla_get_u32(data[IFLA_AMT_MAX_TUNNELS]))3176 amt->max_tunnels = nla_get_u32(data[IFLA_AMT_MAX_TUNNELS]);3177 else3178 amt->max_tunnels = AMT_MAX_TUNNELS;3179 3180 spin_lock_init(&amt->lock);3181 amt->max_groups = AMT_MAX_GROUP;3182 amt->max_sources = AMT_MAX_SOURCE;3183 amt->hash_buckets = AMT_HSIZE;3184 amt->nr_tunnels = 0;3185 get_random_bytes(&amt->hash_seed, sizeof(amt->hash_seed));3186 amt->stream_dev = dev_get_by_index(net,3187 nla_get_u32(data[IFLA_AMT_LINK]));3188 if (!amt->stream_dev) {3189 NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_AMT_LINK],3190 "Can't find stream device");3191 return -ENODEV;3192 }3193 3194 if (amt->stream_dev->type != ARPHRD_ETHER) {3195 NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_AMT_LINK],3196 "Invalid stream device type");3197 goto err;3198 }3199 3200 amt->local_ip = nla_get_in_addr(data[IFLA_AMT_LOCAL_IP]);3201 if (ipv4_is_loopback(amt->local_ip) ||3202 ipv4_is_zeronet(amt->local_ip) ||3203 ipv4_is_multicast(amt->local_ip)) {3204 NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_AMT_LOCAL_IP],3205 "Invalid Local address");3206 goto err;3207 }3208 3209 if (data[IFLA_AMT_RELAY_PORT])3210 amt->relay_port = nla_get_be16(data[IFLA_AMT_RELAY_PORT]);3211 else3212 amt->relay_port = htons(IANA_AMT_UDP_PORT);3213 3214 if (data[IFLA_AMT_GATEWAY_PORT])3215 amt->gw_port = nla_get_be16(data[IFLA_AMT_GATEWAY_PORT]);3216 else3217 amt->gw_port = htons(IANA_AMT_UDP_PORT);3218 3219 if (!amt->relay_port) {3220 NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_AMT_DISCOVERY_IP],3221 "relay port must not be 0");3222 goto err;3223 }3224 if (amt->mode == AMT_MODE_RELAY) {3225 amt->qrv = READ_ONCE(amt->net->ipv4.sysctl_igmp_qrv);3226 amt->qri = 10;3227 dev->needed_headroom = amt->stream_dev->needed_headroom +3228 AMT_RELAY_HLEN;3229 dev->mtu = amt->stream_dev->mtu - AMT_RELAY_HLEN;3230 dev->max_mtu = dev->mtu;3231 dev->min_mtu = ETH_MIN_MTU + AMT_RELAY_HLEN;3232 } else {3233 if (!data[IFLA_AMT_DISCOVERY_IP]) {3234 NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_AMT_DISCOVERY_IP],3235 "discovery must be set in gateway mode");3236 goto err;3237 }3238 if (!amt->gw_port) {3239 NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_AMT_DISCOVERY_IP],3240 "gateway port must not be 0");3241 goto err;3242 }3243 amt->remote_ip = 0;3244 amt->discovery_ip = nla_get_in_addr(data[IFLA_AMT_DISCOVERY_IP]);3245 if (ipv4_is_loopback(amt->discovery_ip) ||3246 ipv4_is_zeronet(amt->discovery_ip) ||3247 ipv4_is_multicast(amt->discovery_ip)) {3248 NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_AMT_DISCOVERY_IP],3249 "discovery must be unicast");3250 goto err;3251 }3252 3253 dev->needed_headroom = amt->stream_dev->needed_headroom +3254 AMT_GW_HLEN;3255 dev->mtu = amt->stream_dev->mtu - AMT_GW_HLEN;3256 dev->max_mtu = dev->mtu;3257 dev->min_mtu = ETH_MIN_MTU + AMT_GW_HLEN;3258 }3259 amt->qi = AMT_INIT_QUERY_INTERVAL;3260 3261 err = register_netdevice(dev);3262 if (err < 0) {3263 netdev_dbg(dev, "failed to register new netdev %d\n", err);3264 goto err;3265 }3266 3267 err = netdev_upper_dev_link(amt->stream_dev, dev, extack);3268 if (err < 0) {3269 unregister_netdevice(dev);3270 goto err;3271 }3272 3273 INIT_DELAYED_WORK(&amt->discovery_wq, amt_discovery_work);3274 INIT_DELAYED_WORK(&amt->req_wq, amt_req_work);3275 INIT_DELAYED_WORK(&amt->secret_wq, amt_secret_work);3276 INIT_WORK(&amt->event_wq, amt_event_work);3277 INIT_LIST_HEAD(&amt->tunnel_list);3278 return 0;3279err:3280 dev_put(amt->stream_dev);3281 return err;3282}3283 3284static void amt_dellink(struct net_device *dev, struct list_head *head)3285{3286 struct amt_dev *amt = netdev_priv(dev);3287 3288 unregister_netdevice_queue(dev, head);3289 netdev_upper_dev_unlink(amt->stream_dev, dev);3290 dev_put(amt->stream_dev);3291}3292 3293static size_t amt_get_size(const struct net_device *dev)3294{3295 return nla_total_size(sizeof(__u32)) + /* IFLA_AMT_MODE */3296 nla_total_size(sizeof(__u16)) + /* IFLA_AMT_RELAY_PORT */3297 nla_total_size(sizeof(__u16)) + /* IFLA_AMT_GATEWAY_PORT */3298 nla_total_size(sizeof(__u32)) + /* IFLA_AMT_LINK */3299 nla_total_size(sizeof(__u32)) + /* IFLA_MAX_TUNNELS */3300 nla_total_size(sizeof(struct iphdr)) + /* IFLA_AMT_DISCOVERY_IP */3301 nla_total_size(sizeof(struct iphdr)) + /* IFLA_AMT_REMOTE_IP */3302 nla_total_size(sizeof(struct iphdr)); /* IFLA_AMT_LOCAL_IP */3303}3304 3305static int amt_fill_info(struct sk_buff *skb, const struct net_device *dev)3306{3307 struct amt_dev *amt = netdev_priv(dev);3308 3309 if (nla_put_u32(skb, IFLA_AMT_MODE, amt->mode))3310 goto nla_put_failure;3311 if (nla_put_be16(skb, IFLA_AMT_RELAY_PORT, amt->relay_port))3312 goto nla_put_failure;3313 if (nla_put_be16(skb, IFLA_AMT_GATEWAY_PORT, amt->gw_port))3314 goto nla_put_failure;3315 if (nla_put_u32(skb, IFLA_AMT_LINK, amt->stream_dev->ifindex))3316 goto nla_put_failure;3317 if (nla_put_in_addr(skb, IFLA_AMT_LOCAL_IP, amt->local_ip))3318 goto nla_put_failure;3319 if (nla_put_in_addr(skb, IFLA_AMT_DISCOVERY_IP, amt->discovery_ip))3320 goto nla_put_failure;3321 if (amt->remote_ip)3322 if (nla_put_in_addr(skb, IFLA_AMT_REMOTE_IP, amt->remote_ip))3323 goto nla_put_failure;3324 if (nla_put_u32(skb, IFLA_AMT_MAX_TUNNELS, amt->max_tunnels))3325 goto nla_put_failure;3326 3327 return 0;3328 3329nla_put_failure:3330 return -EMSGSIZE;3331}3332 3333static struct rtnl_link_ops amt_link_ops __read_mostly = {3334 .kind = "amt",3335 .maxtype = IFLA_AMT_MAX,3336 .policy = amt_policy,3337 .priv_size = sizeof(struct amt_dev),3338 .setup = amt_link_setup,3339 .validate = amt_validate,3340 .newlink = amt_newlink,3341 .dellink = amt_dellink,3342 .get_size = amt_get_size,3343 .fill_info = amt_fill_info,3344};3345 3346static struct net_device *amt_lookup_upper_dev(struct net_device *dev)3347{3348 struct net_device *upper_dev;3349 struct amt_dev *amt;3350 3351 for_each_netdev(dev_net(dev), upper_dev) {3352 if (netif_is_amt(upper_dev)) {3353 amt = netdev_priv(upper_dev);3354 if (amt->stream_dev == dev)3355 return upper_dev;3356 }3357 }3358 3359 return NULL;3360}3361 3362static int amt_device_event(struct notifier_block *unused,3363 unsigned long event, void *ptr)3364{3365 struct net_device *dev = netdev_notifier_info_to_dev(ptr);3366 struct net_device *upper_dev;3367 struct amt_dev *amt;3368 LIST_HEAD(list);3369 int new_mtu;3370 3371 upper_dev = amt_lookup_upper_dev(dev);3372 if (!upper_dev)3373 return NOTIFY_DONE;3374 amt = netdev_priv(upper_dev);3375 3376 switch (event) {3377 case NETDEV_UNREGISTER:3378 amt_dellink(amt->dev, &list);3379 unregister_netdevice_many(&list);3380 break;3381 case NETDEV_CHANGEMTU:3382 if (amt->mode == AMT_MODE_RELAY)3383 new_mtu = dev->mtu - AMT_RELAY_HLEN;3384 else3385 new_mtu = dev->mtu - AMT_GW_HLEN;3386 3387 dev_set_mtu(amt->dev, new_mtu);3388 break;3389 }3390 3391 return NOTIFY_DONE;3392}3393 3394static struct notifier_block amt_notifier_block __read_mostly = {3395 .notifier_call = amt_device_event,3396};3397 3398static int __init amt_init(void)3399{3400 int err;3401 3402 err = register_netdevice_notifier(&amt_notifier_block);3403 if (err < 0)3404 goto err;3405 3406 err = rtnl_link_register(&amt_link_ops);3407 if (err < 0)3408 goto unregister_notifier;3409 3410 amt_wq = alloc_workqueue("amt", WQ_UNBOUND, 0);3411 if (!amt_wq) {3412 err = -ENOMEM;3413 goto rtnl_unregister;3414 }3415 3416 spin_lock_init(&source_gc_lock);3417 spin_lock_bh(&source_gc_lock);3418 INIT_DELAYED_WORK(&source_gc_wq, amt_source_gc_work);3419 mod_delayed_work(amt_wq, &source_gc_wq,3420 msecs_to_jiffies(AMT_GC_INTERVAL));3421 spin_unlock_bh(&source_gc_lock);3422 3423 return 0;3424 3425rtnl_unregister:3426 rtnl_link_unregister(&amt_link_ops);3427unregister_notifier:3428 unregister_netdevice_notifier(&amt_notifier_block);3429err:3430 pr_err("error loading AMT module loaded\n");3431 return err;3432}3433late_initcall(amt_init);3434 3435static void __exit amt_fini(void)3436{3437 rtnl_link_unregister(&amt_link_ops);3438 unregister_netdevice_notifier(&amt_notifier_block);3439 cancel_delayed_work_sync(&source_gc_wq);3440 __amt_source_gc_work();3441 destroy_workqueue(amt_wq);3442}3443module_exit(amt_fini);3444 3445MODULE_LICENSE("GPL");3446MODULE_DESCRIPTION("Driver for Automatic Multicast Tunneling (AMT)");3447MODULE_AUTHOR("Taehee Yoo <ap420073@gmail.com>");3448MODULE_ALIAS_RTNL_LINK("amt");3449