LCOV - code coverage report
Current view: top level - mptcp/pm_netlink.c (source / functions) Coverage Total Hit
Test: export Lines: 76.8 % 311 239
Test Date: 2025-03-31 13:57:41 Functions: 100.0 % 22 22
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 53.7 % 242 130

             Branch data     Line data    Source code
       1                 :             : // SPDX-License-Identifier: GPL-2.0
       2                 :             : /* Multipath TCP
       3                 :             :  *
       4                 :             :  * Copyright (c) 2020, Red Hat, Inc.
       5                 :             :  */
       6                 :             : 
       7                 :             : #define pr_fmt(fmt) "MPTCP: " fmt
       8                 :             : 
       9                 :             : #include "protocol.h"
      10                 :             : #include "mptcp_pm_gen.h"
      11                 :             : 
      12                 :             : #define MPTCP_PM_CMD_GRP_OFFSET       0
      13                 :             : #define MPTCP_PM_EV_GRP_OFFSET        1
      14                 :             : 
      15                 :             : static const struct genl_multicast_group mptcp_pm_mcgrps[] = {
      16                 :             :         [MPTCP_PM_CMD_GRP_OFFSET]       = { .name = MPTCP_PM_CMD_GRP_NAME, },
      17                 :             :         [MPTCP_PM_EV_GRP_OFFSET]        = { .name = MPTCP_PM_EV_GRP_NAME,
      18                 :             :                                             .flags = GENL_MCAST_CAP_NET_ADMIN,
      19                 :             :                                           },
      20                 :             : };
      21                 :             : 
      22                 :          66 : static int mptcp_pm_family_to_addr(int family)
      23                 :             : {
      24                 :             : #if IS_ENABLED(CONFIG_MPTCP_IPV6)
      25                 :        1256 :         if (family == AF_INET6)
      26                 :         106 :                 return MPTCP_PM_ADDR_ATTR_ADDR6;
      27                 :             : #endif
      28                 :             :         return MPTCP_PM_ADDR_ATTR_ADDR4;
      29                 :             : }
      30                 :             : 
      31                 :        1888 : static int mptcp_pm_parse_pm_addr_attr(struct nlattr *tb[],
      32                 :             :                                        const struct nlattr *attr,
      33                 :             :                                        struct genl_info *info,
      34                 :             :                                        struct mptcp_addr_info *addr,
      35                 :             :                                        bool require_family)
      36                 :             : {
      37                 :        1888 :         int err, addr_addr;
      38                 :             : 
      39         [ -  + ]:        1888 :         if (!attr) {
      40         [ #  # ]:           0 :                 GENL_SET_ERR_MSG(info, "missing address info");
      41                 :           0 :                 return -EINVAL;
      42                 :             :         }
      43                 :             : 
      44                 :             :         /* no validation needed - was already done via nested policy */
      45                 :        1888 :         err = nla_parse_nested_deprecated(tb, MPTCP_PM_ADDR_ATTR_MAX, attr,
      46                 :             :                                           mptcp_pm_address_nl_policy, info->extack);
      47         [ +  - ]:        1888 :         if (err)
      48                 :             :                 return err;
      49                 :             : 
      50         [ +  + ]:        1888 :         if (tb[MPTCP_PM_ADDR_ATTR_ID])
      51                 :        1262 :                 addr->id = nla_get_u8(tb[MPTCP_PM_ADDR_ATTR_ID]);
      52                 :             : 
      53         [ +  + ]:        1888 :         if (!tb[MPTCP_PM_ADDR_ATTR_FAMILY]) {
      54         [ +  - ]:         632 :                 if (!require_family)
      55                 :             :                         return 0;
      56                 :             : 
      57         [ #  # ]:           0 :                 NL_SET_ERR_MSG_ATTR(info->extack, attr,
      58                 :             :                                     "missing family");
      59                 :           0 :                 return -EINVAL;
      60                 :             :         }
      61                 :             : 
      62         [ -  + ]:        1256 :         addr->family = nla_get_u16(tb[MPTCP_PM_ADDR_ATTR_FAMILY]);
      63                 :        1256 :         if (addr->family != AF_INET
      64                 :             : #if IS_ENABLED(CONFIG_MPTCP_IPV6)
      65         [ -  + ]:        1256 :             && addr->family != AF_INET6
      66                 :             : #endif
      67                 :             :             ) {
      68         [ #  # ]:           0 :                 NL_SET_ERR_MSG_ATTR(info->extack, attr,
      69                 :             :                                     "unknown address family");
      70                 :           0 :                 return -EINVAL;
      71                 :             :         }
      72         [ +  + ]:        1256 :         addr_addr = mptcp_pm_family_to_addr(addr->family);
      73         [ -  + ]:        1256 :         if (!tb[addr_addr]) {
      74         [ #  # ]:           0 :                 NL_SET_ERR_MSG_ATTR(info->extack, attr,
      75                 :             :                                     "missing address data");
      76                 :           0 :                 return -EINVAL;
      77                 :             :         }
      78                 :             : 
      79                 :             : #if IS_ENABLED(CONFIG_MPTCP_IPV6)
      80         [ +  + ]:        1256 :         if (addr->family == AF_INET6)
      81                 :         106 :                 addr->addr6 = nla_get_in6_addr(tb[addr_addr]);
      82                 :             :         else
      83                 :             : #endif
      84                 :        1150 :                 addr->addr.s_addr = nla_get_in_addr(tb[addr_addr]);
      85                 :             : 
      86         [ +  + ]:        1256 :         if (tb[MPTCP_PM_ADDR_ATTR_PORT])
      87                 :          96 :                 addr->port = htons(nla_get_u16(tb[MPTCP_PM_ADDR_ATTR_PORT]));
      88                 :             : 
      89                 :             :         return 0;
      90                 :             : }
      91                 :             : 
      92                 :          44 : int mptcp_pm_parse_addr(struct nlattr *attr, struct genl_info *info,
      93                 :             :                         struct mptcp_addr_info *addr)
      94                 :             : {
      95                 :          44 :         struct nlattr *tb[MPTCP_PM_ADDR_ATTR_MAX + 1];
      96                 :             : 
      97                 :          44 :         memset(addr, 0, sizeof(*addr));
      98                 :             : 
      99                 :          44 :         return mptcp_pm_parse_pm_addr_attr(tb, attr, info, addr, true);
     100                 :             : }
     101                 :             : 
     102                 :        1844 : int mptcp_pm_parse_entry(struct nlattr *attr, struct genl_info *info,
     103                 :             :                          bool require_family,
     104                 :             :                          struct mptcp_pm_addr_entry *entry)
     105                 :             : {
     106                 :        1844 :         struct nlattr *tb[MPTCP_PM_ADDR_ATTR_MAX + 1];
     107                 :        1844 :         int err;
     108                 :             : 
     109                 :        1844 :         memset(entry, 0, sizeof(*entry));
     110                 :             : 
     111                 :        1844 :         err = mptcp_pm_parse_pm_addr_attr(tb, attr, info, &entry->addr, require_family);
     112         [ +  - ]:        1844 :         if (err)
     113                 :             :                 return err;
     114                 :             : 
     115         [ +  + ]:        1844 :         if (tb[MPTCP_PM_ADDR_ATTR_IF_IDX]) {
     116                 :          62 :                 u32 val = nla_get_s32(tb[MPTCP_PM_ADDR_ATTR_IF_IDX]);
     117                 :             : 
     118                 :          62 :                 entry->ifindex = val;
     119                 :             :         }
     120                 :             : 
     121         [ +  + ]:        1844 :         if (tb[MPTCP_PM_ADDR_ATTR_FLAGS])
     122                 :         700 :                 entry->flags = nla_get_u32(tb[MPTCP_PM_ADDR_ATTR_FLAGS]);
     123                 :             : 
     124         [ +  + ]:        1844 :         if (tb[MPTCP_PM_ADDR_ATTR_PORT])
     125                 :          52 :                 entry->addr.port = htons(nla_get_u16(tb[MPTCP_PM_ADDR_ATTR_PORT]));
     126                 :             : 
     127                 :             :         return 0;
     128                 :             : }
     129                 :             : 
     130                 :         204 : static int mptcp_nl_fill_addr(struct sk_buff *skb,
     131                 :             :                               struct mptcp_pm_addr_entry *entry)
     132                 :             : {
     133                 :         204 :         struct mptcp_addr_info *addr = &entry->addr;
     134                 :         204 :         struct nlattr *attr;
     135                 :             : 
     136                 :         204 :         attr = nla_nest_start(skb, MPTCP_PM_ATTR_ADDR);
     137         [ -  + ]:         204 :         if (!attr)
     138                 :             :                 return -EMSGSIZE;
     139                 :             : 
     140         [ -  + ]:         204 :         if (nla_put_u16(skb, MPTCP_PM_ADDR_ATTR_FAMILY, addr->family))
     141                 :           0 :                 goto nla_put_failure;
     142         [ -  + ]:         204 :         if (nla_put_u16(skb, MPTCP_PM_ADDR_ATTR_PORT, ntohs(addr->port)))
     143                 :           0 :                 goto nla_put_failure;
     144         [ -  + ]:         204 :         if (nla_put_u8(skb, MPTCP_PM_ADDR_ATTR_ID, addr->id))
     145                 :           0 :                 goto nla_put_failure;
     146         [ -  + ]:         204 :         if (nla_put_u32(skb, MPTCP_PM_ADDR_ATTR_FLAGS, entry->flags))
     147                 :           0 :                 goto nla_put_failure;
     148   [ +  +  -  + ]:         210 :         if (entry->ifindex &&
     149         [ #  # ]:           0 :             nla_put_s32(skb, MPTCP_PM_ADDR_ATTR_IF_IDX, entry->ifindex))
     150                 :           0 :                 goto nla_put_failure;
     151                 :             : 
     152   [ +  +  -  + ]:         390 :         if (addr->family == AF_INET &&
     153         [ #  # ]:         186 :             nla_put_in_addr(skb, MPTCP_PM_ADDR_ATTR_ADDR4,
     154                 :             :                             addr->addr.s_addr))
     155                 :           0 :                 goto nla_put_failure;
     156                 :             : #if IS_ENABLED(CONFIG_MPTCP_IPV6)
     157   [ +  +  -  + ]:         222 :         else if (addr->family == AF_INET6 &&
     158         [ #  # ]:          18 :                  nla_put_in6_addr(skb, MPTCP_PM_ADDR_ATTR_ADDR6, &addr->addr6))
     159                 :           0 :                 goto nla_put_failure;
     160                 :             : #endif
     161                 :         204 :         nla_nest_end(skb, attr);
     162                 :         204 :         return 0;
     163                 :             : 
     164                 :           0 : nla_put_failure:
     165                 :           0 :         nla_nest_cancel(skb, attr);
     166                 :           0 :         return -EMSGSIZE;
     167                 :             : }
     168                 :             : 
     169                 :          28 : static int mptcp_pm_get_addr(u8 id, struct mptcp_pm_addr_entry *addr,
     170                 :             :                              struct genl_info *info)
     171                 :             : {
     172         [ +  + ]:          28 :         if (info->attrs[MPTCP_PM_ATTR_TOKEN])
     173                 :           6 :                 return mptcp_userspace_pm_get_addr(id, addr, info);
     174                 :          22 :         return mptcp_pm_nl_get_addr(id, addr, info);
     175                 :             : }
     176                 :             : 
     177                 :          28 : int mptcp_pm_nl_get_addr_doit(struct sk_buff *skb, struct genl_info *info)
     178                 :             : {
     179                 :          28 :         struct mptcp_pm_addr_entry addr;
     180                 :          28 :         struct nlattr *attr;
     181                 :          28 :         struct sk_buff *msg;
     182                 :          28 :         void *reply;
     183                 :          28 :         int ret;
     184                 :             : 
     185   [ +  -  -  - ]:          28 :         if (GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ENDPOINT_ADDR))
     186                 :           0 :                 return -EINVAL;
     187                 :             : 
     188                 :          28 :         attr = info->attrs[MPTCP_PM_ENDPOINT_ADDR];
     189                 :          28 :         ret = mptcp_pm_parse_entry(attr, info, false, &addr);
     190         [ +  - ]:          28 :         if (ret < 0)
     191                 :             :                 return ret;
     192                 :             : 
     193                 :          28 :         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
     194         [ +  - ]:          28 :         if (!msg)
     195                 :             :                 return -ENOMEM;
     196                 :             : 
     197                 :          28 :         reply = genlmsg_put_reply(msg, info, &mptcp_genl_family, 0,
     198                 :          28 :                                   info->genlhdr->cmd);
     199         [ -  + ]:          28 :         if (!reply) {
     200         [ #  # ]:           0 :                 GENL_SET_ERR_MSG(info, "not enough space in Netlink message");
     201                 :           0 :                 ret = -EMSGSIZE;
     202                 :           0 :                 goto fail;
     203                 :             :         }
     204                 :             : 
     205                 :          28 :         ret = mptcp_pm_get_addr(addr.addr.id, &addr, info);
     206         [ +  + ]:          28 :         if (ret) {
     207         [ +  - ]:           6 :                 NL_SET_ERR_MSG_ATTR(info->extack, attr, "address not found");
     208                 :           6 :                 goto fail;
     209                 :             :         }
     210                 :             : 
     211                 :          22 :         ret = mptcp_nl_fill_addr(msg, &addr);
     212         [ -  + ]:          22 :         if (ret)
     213                 :           0 :                 goto fail;
     214                 :             : 
     215                 :          22 :         genlmsg_end(msg, reply);
     216                 :          22 :         ret = genlmsg_reply(msg, info);
     217                 :          22 :         return ret;
     218                 :             : 
     219                 :           6 : fail:
     220                 :           6 :         nlmsg_free(msg);
     221                 :           6 :         return ret;
     222                 :             : }
     223                 :             : 
     224                 :         182 : int mptcp_pm_genl_fill_addr(struct sk_buff *msg,
     225                 :             :                             struct netlink_callback *cb,
     226                 :             :                             struct mptcp_pm_addr_entry *entry)
     227                 :             : {
     228                 :         182 :         void *hdr;
     229                 :             : 
     230                 :         182 :         hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).portid,
     231                 :         182 :                           cb->nlh->nlmsg_seq, &mptcp_genl_family,
     232                 :             :                           NLM_F_MULTI, MPTCP_PM_CMD_GET_ADDR);
     233         [ -  + ]:         182 :         if (!hdr)
     234                 :             :                 return -EINVAL;
     235                 :             : 
     236         [ -  + ]:         182 :         if (mptcp_nl_fill_addr(msg, entry) < 0) {
     237                 :           0 :                 genlmsg_cancel(msg, hdr);
     238                 :           0 :                 return -EINVAL;
     239                 :             :         }
     240                 :             : 
     241                 :         182 :         genlmsg_end(msg, hdr);
     242                 :         182 :         return 0;
     243                 :             : }
     244                 :             : 
     245                 :         236 : static int mptcp_pm_dump_addr(struct sk_buff *msg, struct netlink_callback *cb)
     246                 :             : {
     247         [ +  + ]:         236 :         const struct genl_info *info = genl_info_dump(cb);
     248                 :             : 
     249         [ +  + ]:         236 :         if (info->attrs[MPTCP_PM_ATTR_TOKEN])
     250                 :          20 :                 return mptcp_userspace_pm_dump_addr(msg, cb);
     251                 :         216 :         return mptcp_pm_nl_dump_addr(msg, cb);
     252                 :             : }
     253                 :             : 
     254                 :         236 : int mptcp_pm_nl_get_addr_dumpit(struct sk_buff *msg,
     255                 :             :                                 struct netlink_callback *cb)
     256                 :             : {
     257                 :         236 :         return mptcp_pm_dump_addr(msg, cb);
     258                 :             : }
     259                 :             : 
     260                 :          48 : static int mptcp_pm_set_flags(struct genl_info *info)
     261                 :             : {
     262                 :          48 :         struct mptcp_pm_addr_entry loc = { .addr = { .family = AF_UNSPEC }, };
     263                 :          48 :         struct nlattr *attr_loc;
     264                 :          48 :         int ret = -EINVAL;
     265                 :             : 
     266   [ +  -  -  - ]:          48 :         if (GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ATTR_ADDR))
     267                 :           0 :                 return ret;
     268                 :             : 
     269                 :          48 :         attr_loc = info->attrs[MPTCP_PM_ATTR_ADDR];
     270                 :          48 :         ret = mptcp_pm_parse_entry(attr_loc, info, false, &loc);
     271         [ +  - ]:          48 :         if (ret < 0)
     272                 :             :                 return ret;
     273                 :             : 
     274         [ +  + ]:          48 :         if (info->attrs[MPTCP_PM_ATTR_TOKEN])
     275                 :           2 :                 return mptcp_userspace_pm_set_flags(&loc, info);
     276                 :          46 :         return mptcp_pm_nl_set_flags(&loc, info);
     277                 :             : }
     278                 :             : 
     279                 :          48 : int mptcp_pm_nl_set_flags_doit(struct sk_buff *skb, struct genl_info *info)
     280                 :             : {
     281                 :          48 :         return mptcp_pm_set_flags(info);
     282                 :             : }
     283                 :             : 
     284                 :         428 : static void mptcp_nl_mcast_send(struct net *net, struct sk_buff *nlskb, gfp_t gfp)
     285                 :             : {
     286                 :         428 :         genlmsg_multicast_netns(&mptcp_genl_family, net,
     287                 :             :                                 nlskb, 0, MPTCP_PM_EV_GRP_OFFSET, gfp);
     288                 :         428 : }
     289                 :             : 
     290                 :          78 : bool mptcp_userspace_pm_active(const struct mptcp_sock *msk)
     291                 :             : {
     292                 :          78 :         return genl_has_listeners(&mptcp_genl_family,
     293                 :             :                                   sock_net((const struct sock *)msk),
     294                 :             :                                   MPTCP_PM_EV_GRP_OFFSET);
     295                 :             : }
     296                 :             : 
     297                 :         268 : static int mptcp_event_add_subflow(struct sk_buff *skb, const struct sock *ssk)
     298                 :             : {
     299                 :         268 :         const struct inet_sock *issk = inet_sk(ssk);
     300                 :         268 :         const struct mptcp_subflow_context *sf;
     301                 :             : 
     302         [ -  + ]:         268 :         if (nla_put_u16(skb, MPTCP_ATTR_FAMILY, ssk->sk_family))
     303                 :             :                 return -EMSGSIZE;
     304                 :             : 
     305      [ +  +  - ]:         268 :         switch (ssk->sk_family) {
     306                 :         150 :         case AF_INET:
     307         [ -  + ]:         150 :                 if (nla_put_in_addr(skb, MPTCP_ATTR_SADDR4, issk->inet_saddr))
     308                 :             :                         return -EMSGSIZE;
     309         [ -  + ]:         150 :                 if (nla_put_in_addr(skb, MPTCP_ATTR_DADDR4, issk->inet_daddr))
     310                 :             :                         return -EMSGSIZE;
     311                 :             :                 break;
     312                 :             : #if IS_ENABLED(CONFIG_MPTCP_IPV6)
     313                 :         118 :         case AF_INET6: {
     314         [ -  + ]:         118 :                 if (nla_put_in6_addr(skb, MPTCP_ATTR_SADDR6, &issk->pinet6->saddr))
     315                 :             :                         return -EMSGSIZE;
     316         [ -  + ]:         118 :                 if (nla_put_in6_addr(skb, MPTCP_ATTR_DADDR6, &ssk->sk_v6_daddr))
     317                 :             :                         return -EMSGSIZE;
     318                 :             :                 break;
     319                 :             :         }
     320                 :             : #endif
     321                 :             :         default:
     322                 :           0 :                 WARN_ON_ONCE(1);
     323                 :           0 :                 return -EMSGSIZE;
     324                 :             :         }
     325                 :             : 
     326         [ -  + ]:         268 :         if (nla_put_be16(skb, MPTCP_ATTR_SPORT, issk->inet_sport))
     327                 :             :                 return -EMSGSIZE;
     328         [ -  + ]:         268 :         if (nla_put_be16(skb, MPTCP_ATTR_DPORT, issk->inet_dport))
     329                 :             :                 return -EMSGSIZE;
     330                 :             : 
     331         [ -  + ]:         268 :         sf = mptcp_subflow_ctx(ssk);
     332         [ -  + ]:         268 :         if (WARN_ON_ONCE(!sf))
     333                 :           0 :                 return -EINVAL;
     334                 :             : 
     335         [ -  + ]:         268 :         if (nla_put_u8(skb, MPTCP_ATTR_LOC_ID, subflow_get_local_id(sf)))
     336                 :             :                 return -EMSGSIZE;
     337                 :             : 
     338         [ -  + ]:         268 :         if (nla_put_u8(skb, MPTCP_ATTR_REM_ID, sf->remote_id))
     339                 :             :                 return -EMSGSIZE;
     340                 :             : 
     341                 :             :         return 0;
     342                 :             : }
     343                 :             : 
     344                 :         188 : static int mptcp_event_put_token_and_ssk(struct sk_buff *skb,
     345                 :             :                                          const struct mptcp_sock *msk,
     346                 :             :                                          const struct sock *ssk)
     347                 :             : {
     348                 :         188 :         const struct sock *sk = (const struct sock *)msk;
     349                 :         188 :         const struct mptcp_subflow_context *sf;
     350                 :         188 :         u8 sk_err;
     351                 :             : 
     352         [ -  + ]:         188 :         if (nla_put_u32(skb, MPTCP_ATTR_TOKEN, READ_ONCE(msk->token)))
     353                 :             :                 return -EMSGSIZE;
     354                 :             : 
     355         [ -  + ]:         188 :         if (mptcp_event_add_subflow(skb, ssk))
     356                 :             :                 return -EMSGSIZE;
     357                 :             : 
     358         [ -  + ]:         188 :         sf = mptcp_subflow_ctx(ssk);
     359         [ -  + ]:         188 :         if (WARN_ON_ONCE(!sf))
     360                 :           0 :                 return -EINVAL;
     361                 :             : 
     362         [ -  + ]:         188 :         if (nla_put_u8(skb, MPTCP_ATTR_BACKUP, sf->backup))
     363                 :             :                 return -EMSGSIZE;
     364                 :             : 
     365   [ +  +  -  + ]:         204 :         if (ssk->sk_bound_dev_if &&
     366         [ #  # ]:           0 :             nla_put_s32(skb, MPTCP_ATTR_IF_IDX, ssk->sk_bound_dev_if))
     367                 :             :                 return -EMSGSIZE;
     368                 :             : 
     369                 :         188 :         sk_err = READ_ONCE(ssk->sk_err);
     370   [ -  +  -  -  :         188 :         if (sk_err && sk->sk_state == TCP_ESTABLISHED &&
                   -  - ]
     371         [ #  # ]:           0 :             nla_put_u8(skb, MPTCP_ATTR_ERROR, sk_err))
     372                 :             :                 return -EMSGSIZE;
     373                 :             : 
     374                 :             :         return 0;
     375                 :             : }
     376                 :             : 
     377                 :           0 : static int mptcp_event_sub_established(struct sk_buff *skb,
     378                 :             :                                        const struct mptcp_sock *msk,
     379                 :             :                                        const struct sock *ssk)
     380                 :             : {
     381                 :         106 :         return mptcp_event_put_token_and_ssk(skb, msk, ssk);
     382                 :             : }
     383                 :             : 
     384                 :          82 : static int mptcp_event_sub_closed(struct sk_buff *skb,
     385                 :             :                                   const struct mptcp_sock *msk,
     386                 :             :                                   const struct sock *ssk)
     387                 :             : {
     388                 :          82 :         const struct mptcp_subflow_context *sf;
     389                 :             : 
     390         [ -  + ]:          82 :         if (mptcp_event_put_token_and_ssk(skb, msk, ssk))
     391                 :             :                 return -EMSGSIZE;
     392                 :             : 
     393         [ +  - ]:          82 :         sf = mptcp_subflow_ctx(ssk);
     394         [ +  - ]:          82 :         if (!sf->reset_seen)
     395                 :             :                 return 0;
     396                 :             : 
     397         [ #  # ]:           0 :         if (nla_put_u32(skb, MPTCP_ATTR_RESET_REASON, sf->reset_reason))
     398                 :             :                 return -EMSGSIZE;
     399                 :             : 
     400         [ #  # ]:           0 :         if (nla_put_u32(skb, MPTCP_ATTR_RESET_FLAGS, sf->reset_transient))
     401                 :             :                 return -EMSGSIZE;
     402                 :             : 
     403                 :             :         return 0;
     404                 :             : }
     405                 :             : 
     406                 :          80 : static int mptcp_event_created(struct sk_buff *skb,
     407                 :             :                                const struct mptcp_sock *msk,
     408                 :             :                                const struct sock *ssk)
     409                 :             : {
     410                 :          80 :         int err = nla_put_u32(skb, MPTCP_ATTR_TOKEN, READ_ONCE(msk->token));
     411                 :             : 
     412         [ +  - ]:          80 :         if (err)
     413                 :             :                 return err;
     414                 :             : 
     415   [ +  +  +  - ]:         120 :         if (nla_put_u8(skb, MPTCP_ATTR_SERVER_SIDE, READ_ONCE(msk->pm.server_side)))
     416                 :             :                 return -EMSGSIZE;
     417                 :             : 
     418                 :          80 :         return mptcp_event_add_subflow(skb, ssk);
     419                 :             : }
     420                 :             : 
     421                 :         114 : void mptcp_event_addr_removed(const struct mptcp_sock *msk, uint8_t id)
     422                 :             : {
     423                 :         114 :         struct net *net = sock_net((const struct sock *)msk);
     424                 :         114 :         struct nlmsghdr *nlh;
     425                 :         114 :         struct sk_buff *skb;
     426                 :             : 
     427         [ +  + ]:         114 :         if (!genl_has_listeners(&mptcp_genl_family, net, MPTCP_PM_EV_GRP_OFFSET))
     428                 :             :                 return;
     429                 :             : 
     430                 :          48 :         skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
     431         [ +  - ]:          48 :         if (!skb)
     432                 :             :                 return;
     433                 :             : 
     434                 :          48 :         nlh = genlmsg_put(skb, 0, 0, &mptcp_genl_family, 0, MPTCP_EVENT_REMOVED);
     435         [ -  + ]:          48 :         if (!nlh)
     436                 :           0 :                 goto nla_put_failure;
     437                 :             : 
     438         [ -  + ]:          48 :         if (nla_put_u32(skb, MPTCP_ATTR_TOKEN, READ_ONCE(msk->token)))
     439                 :           0 :                 goto nla_put_failure;
     440                 :             : 
     441         [ -  + ]:          48 :         if (nla_put_u8(skb, MPTCP_ATTR_REM_ID, id))
     442                 :           0 :                 goto nla_put_failure;
     443                 :             : 
     444                 :          48 :         genlmsg_end(skb, nlh);
     445                 :          48 :         mptcp_nl_mcast_send(net, skb, GFP_ATOMIC);
     446                 :          48 :         return;
     447                 :             : 
     448                 :           0 : nla_put_failure:
     449                 :           0 :         nlmsg_free(skb);
     450                 :             : }
     451                 :             : 
     452                 :         366 : void mptcp_event_addr_announced(const struct sock *ssk,
     453                 :             :                                 const struct mptcp_addr_info *info)
     454                 :             : {
     455         [ -  + ]:         366 :         struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
     456         [ -  + ]:         366 :         struct mptcp_sock *msk = mptcp_sk(subflow->conn);
     457                 :         366 :         struct net *net = sock_net(ssk);
     458                 :         366 :         struct nlmsghdr *nlh;
     459                 :         366 :         struct sk_buff *skb;
     460                 :             : 
     461         [ +  + ]:         366 :         if (!genl_has_listeners(&mptcp_genl_family, net, MPTCP_PM_EV_GRP_OFFSET))
     462                 :             :                 return;
     463                 :             : 
     464                 :          48 :         skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
     465         [ +  - ]:          48 :         if (!skb)
     466                 :             :                 return;
     467                 :             : 
     468                 :          48 :         nlh = genlmsg_put(skb, 0, 0, &mptcp_genl_family, 0,
     469                 :             :                           MPTCP_EVENT_ANNOUNCED);
     470         [ -  + ]:          48 :         if (!nlh)
     471                 :           0 :                 goto nla_put_failure;
     472                 :             : 
     473         [ -  + ]:          48 :         if (nla_put_u32(skb, MPTCP_ATTR_TOKEN, READ_ONCE(msk->token)))
     474                 :           0 :                 goto nla_put_failure;
     475                 :             : 
     476         [ -  + ]:          48 :         if (nla_put_u8(skb, MPTCP_ATTR_REM_ID, info->id))
     477                 :           0 :                 goto nla_put_failure;
     478                 :             : 
     479         [ -  + ]:          48 :         if (nla_put_be16(skb, MPTCP_ATTR_DPORT,
     480         [ +  + ]:          48 :                          info->port == 0 ?
     481                 :          38 :                          inet_sk(ssk)->inet_dport :
     482                 :             :                          info->port))
     483                 :           0 :                 goto nla_put_failure;
     484                 :             : 
     485      [ +  +  - ]:          48 :         switch (info->family) {
     486                 :          40 :         case AF_INET:
     487         [ -  + ]:          40 :                 if (nla_put_in_addr(skb, MPTCP_ATTR_DADDR4, info->addr.s_addr))
     488                 :           0 :                         goto nla_put_failure;
     489                 :             :                 break;
     490                 :             : #if IS_ENABLED(CONFIG_MPTCP_IPV6)
     491                 :           8 :         case AF_INET6:
     492         [ -  + ]:           8 :                 if (nla_put_in6_addr(skb, MPTCP_ATTR_DADDR6, &info->addr6))
     493                 :           0 :                         goto nla_put_failure;
     494                 :             :                 break;
     495                 :             : #endif
     496                 :             :         default:
     497                 :           0 :                 WARN_ON_ONCE(1);
     498                 :           0 :                 goto nla_put_failure;
     499                 :             :         }
     500                 :             : 
     501                 :          48 :         genlmsg_end(skb, nlh);
     502                 :          48 :         mptcp_nl_mcast_send(net, skb, GFP_ATOMIC);
     503                 :          48 :         return;
     504                 :             : 
     505                 :           0 : nla_put_failure:
     506                 :           0 :         nlmsg_free(skb);
     507                 :             : }
     508                 :             : 
     509                 :        2522 : void mptcp_event_pm_listener(const struct sock *ssk,
     510                 :             :                              enum mptcp_event_type event)
     511                 :             : {
     512                 :        2522 :         const struct inet_sock *issk = inet_sk(ssk);
     513                 :        2522 :         struct net *net = sock_net(ssk);
     514                 :        2522 :         struct nlmsghdr *nlh;
     515                 :        2522 :         struct sk_buff *skb;
     516                 :             : 
     517         [ +  + ]:        2522 :         if (!genl_has_listeners(&mptcp_genl_family, net, MPTCP_PM_EV_GRP_OFFSET))
     518                 :             :                 return;
     519                 :             : 
     520                 :          52 :         skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
     521         [ +  - ]:          52 :         if (!skb)
     522                 :             :                 return;
     523                 :             : 
     524                 :          52 :         nlh = genlmsg_put(skb, 0, 0, &mptcp_genl_family, 0, event);
     525         [ -  + ]:          52 :         if (!nlh)
     526                 :           0 :                 goto nla_put_failure;
     527                 :             : 
     528         [ -  + ]:          52 :         if (nla_put_u16(skb, MPTCP_ATTR_FAMILY, ssk->sk_family))
     529                 :           0 :                 goto nla_put_failure;
     530                 :             : 
     531         [ -  + ]:          52 :         if (nla_put_be16(skb, MPTCP_ATTR_SPORT, issk->inet_sport))
     532                 :           0 :                 goto nla_put_failure;
     533                 :             : 
     534      [ +  +  - ]:          52 :         switch (ssk->sk_family) {
     535                 :          26 :         case AF_INET:
     536         [ -  + ]:          26 :                 if (nla_put_in_addr(skb, MPTCP_ATTR_SADDR4, issk->inet_saddr))
     537                 :           0 :                         goto nla_put_failure;
     538                 :             :                 break;
     539                 :             : #if IS_ENABLED(CONFIG_MPTCP_IPV6)
     540                 :          26 :         case AF_INET6: {
     541         [ -  + ]:          26 :                 if (nla_put_in6_addr(skb, MPTCP_ATTR_SADDR6, &issk->pinet6->saddr))
     542                 :           0 :                         goto nla_put_failure;
     543                 :             :                 break;
     544                 :             :         }
     545                 :             : #endif
     546                 :             :         default:
     547                 :           0 :                 WARN_ON_ONCE(1);
     548                 :           0 :                 goto nla_put_failure;
     549                 :             :         }
     550                 :             : 
     551                 :          52 :         genlmsg_end(skb, nlh);
     552                 :          52 :         mptcp_nl_mcast_send(net, skb, GFP_KERNEL);
     553                 :          52 :         return;
     554                 :             : 
     555                 :           0 : nla_put_failure:
     556                 :           0 :         nlmsg_free(skb);
     557                 :             : }
     558                 :             : 
     559                 :        8190 : void mptcp_event(enum mptcp_event_type type, const struct mptcp_sock *msk,
     560                 :             :                  const struct sock *ssk, gfp_t gfp)
     561                 :             : {
     562                 :        8190 :         struct net *net = sock_net((const struct sock *)msk);
     563                 :        8190 :         struct nlmsghdr *nlh;
     564                 :        8190 :         struct sk_buff *skb;
     565                 :             : 
     566         [ +  + ]:        8190 :         if (!genl_has_listeners(&mptcp_genl_family, net, MPTCP_PM_EV_GRP_OFFSET))
     567                 :             :                 return;
     568                 :             : 
     569                 :         280 :         skb = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
     570         [ +  - ]:         280 :         if (!skb)
     571                 :             :                 return;
     572                 :             : 
     573                 :         280 :         nlh = genlmsg_put(skb, 0, 0, &mptcp_genl_family, 0, type);
     574         [ -  + ]:         280 :         if (!nlh)
     575                 :           0 :                 goto nla_put_failure;
     576                 :             : 
     577   [ -  +  +  -  :         280 :         switch (type) {
                +  +  - ]
     578                 :             :         case MPTCP_EVENT_UNSPEC:
     579                 :           0 :                 WARN_ON_ONCE(1);
     580                 :           0 :                 break;
     581                 :          80 :         case MPTCP_EVENT_CREATED:
     582                 :             :         case MPTCP_EVENT_ESTABLISHED:
     583         [ -  + ]:          80 :                 if (mptcp_event_created(skb, msk, ssk) < 0)
     584                 :           0 :                         goto nla_put_failure;
     585                 :             :                 break;
     586                 :             :         case MPTCP_EVENT_CLOSED:
     587         [ -  + ]:          12 :                 if (nla_put_u32(skb, MPTCP_ATTR_TOKEN, READ_ONCE(msk->token)) < 0)
     588                 :           0 :                         goto nla_put_failure;
     589                 :             :                 break;
     590                 :             :         case MPTCP_EVENT_ANNOUNCED:
     591                 :             :         case MPTCP_EVENT_REMOVED:
     592                 :             :                 /* call mptcp_event_addr_announced()/removed instead */
     593                 :           0 :                 WARN_ON_ONCE(1);
     594                 :           0 :                 break;
     595                 :             :         case MPTCP_EVENT_SUB_ESTABLISHED:
     596                 :             :         case MPTCP_EVENT_SUB_PRIORITY:
     597         [ -  + ]:         106 :                 if (mptcp_event_sub_established(skb, msk, ssk) < 0)
     598                 :           0 :                         goto nla_put_failure;
     599                 :             :                 break;
     600                 :          82 :         case MPTCP_EVENT_SUB_CLOSED:
     601         [ -  + ]:          82 :                 if (mptcp_event_sub_closed(skb, msk, ssk) < 0)
     602                 :           0 :                         goto nla_put_failure;
     603                 :             :                 break;
     604                 :             :         case MPTCP_EVENT_LISTENER_CREATED:
     605                 :             :         case MPTCP_EVENT_LISTENER_CLOSED:
     606                 :             :                 break;
     607                 :             :         }
     608                 :             : 
     609                 :         280 :         genlmsg_end(skb, nlh);
     610                 :         280 :         mptcp_nl_mcast_send(net, skb, gfp);
     611                 :         280 :         return;
     612                 :             : 
     613                 :           0 : nla_put_failure:
     614                 :           0 :         nlmsg_free(skb);
     615                 :             : }
     616                 :             : 
     617                 :             : struct genl_family mptcp_genl_family __ro_after_init = {
     618                 :             :         .name           = MPTCP_PM_NAME,
     619                 :             :         .version        = MPTCP_PM_VER,
     620                 :             :         .netnsok        = true,
     621                 :             :         .module         = THIS_MODULE,
     622                 :             :         .ops            = mptcp_pm_nl_ops,
     623                 :             :         .n_ops          = ARRAY_SIZE(mptcp_pm_nl_ops),
     624                 :             :         .resv_start_op  = MPTCP_PM_CMD_SUBFLOW_DESTROY + 1,
     625                 :             :         .mcgrps         = mptcp_pm_mcgrps,
     626                 :             :         .n_mcgrps       = ARRAY_SIZE(mptcp_pm_mcgrps),
     627                 :             : };
     628                 :             : 
     629                 :           4 : void __init mptcp_pm_nl_init(void)
     630                 :             : {
     631         [ -  + ]:           4 :         if (genl_register_family(&mptcp_genl_family))
     632                 :           0 :                 panic("Failed to register MPTCP PM netlink family\n");
     633                 :           4 : }
        

Generated by: LCOV version 2.0-1