.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* GTP according to GSM TS 09.60 / 3GPP TS 29.060 |
---|
2 | 3 | * |
---|
3 | 4 | * (C) 2012-2014 by sysmocom - s.f.m.c. GmbH |
---|
.. | .. |
---|
6 | 7 | * Author: Harald Welte <hwelte@sysmocom.de> |
---|
7 | 8 | * Pablo Neira Ayuso <pablo@netfilter.org> |
---|
8 | 9 | * Andreas Schultz <aschultz@travelping.com> |
---|
9 | | - * |
---|
10 | | - * This program is free software; you can redistribute it and/or |
---|
11 | | - * modify it under the terms of the GNU General Public License |
---|
12 | | - * as published by the Free Software Foundation; either version |
---|
13 | | - * 2 of the License, or (at your option) any later version. |
---|
14 | 10 | */ |
---|
15 | 11 | |
---|
16 | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
---|
.. | .. |
---|
186 | 182 | static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, |
---|
187 | 183 | unsigned int hdrlen, unsigned int role) |
---|
188 | 184 | { |
---|
189 | | - struct pcpu_sw_netstats *stats; |
---|
190 | | - |
---|
191 | 185 | if (!gtp_check_ms(skb, pctx, hdrlen, role)) { |
---|
192 | 186 | netdev_dbg(pctx->dev, "No PDP ctx for this MS\n"); |
---|
193 | 187 | return 1; |
---|
.. | .. |
---|
208 | 202 | |
---|
209 | 203 | skb->dev = pctx->dev; |
---|
210 | 204 | |
---|
211 | | - stats = this_cpu_ptr(pctx->dev->tstats); |
---|
212 | | - u64_stats_update_begin(&stats->syncp); |
---|
213 | | - stats->rx_packets++; |
---|
214 | | - stats->rx_bytes += skb->len; |
---|
215 | | - u64_stats_update_end(&stats->syncp); |
---|
| 205 | + dev_sw_netstats_rx_add(pctx->dev, skb->len); |
---|
216 | 206 | |
---|
217 | 207 | netif_rx(skb); |
---|
218 | 208 | return 0; |
---|
.. | .. |
---|
301 | 291 | gtp->sk1u = NULL; |
---|
302 | 292 | udp_sk(sk)->encap_type = 0; |
---|
303 | 293 | rcu_assign_sk_user_data(sk, NULL); |
---|
| 294 | + release_sock(sk); |
---|
304 | 295 | sock_put(sk); |
---|
| 296 | + return; |
---|
305 | 297 | } |
---|
306 | 298 | release_sock(sk); |
---|
307 | 299 | } |
---|
.. | .. |
---|
714 | 706 | hlist_for_each_entry_rcu(pctx, >p->tid_hash[i], hlist_tid) |
---|
715 | 707 | pdp_context_delete(pctx); |
---|
716 | 708 | |
---|
717 | | - gtp_encap_disable(gtp); |
---|
718 | 709 | list_del_rcu(>p->list); |
---|
719 | 710 | unregister_netdevice_queue(dev, head); |
---|
720 | 711 | } |
---|
.. | .. |
---|
858 | 849 | |
---|
859 | 850 | sk1u = gtp_encap_enable_socket(fd1, UDP_ENCAP_GTP1U, gtp); |
---|
860 | 851 | if (IS_ERR(sk1u)) { |
---|
861 | | - if (sk0) |
---|
862 | | - gtp_encap_disable_sock(sk0); |
---|
| 852 | + gtp_encap_disable_sock(sk0); |
---|
863 | 853 | return PTR_ERR(sk1u); |
---|
864 | 854 | } |
---|
865 | 855 | } |
---|
.. | .. |
---|
867 | 857 | if (data[IFLA_GTP_ROLE]) { |
---|
868 | 858 | role = nla_get_u32(data[IFLA_GTP_ROLE]); |
---|
869 | 859 | if (role > GTP_ROLE_SGSN) { |
---|
870 | | - if (sk0) |
---|
871 | | - gtp_encap_disable_sock(sk0); |
---|
872 | | - if (sk1u) |
---|
873 | | - gtp_encap_disable_sock(sk1u); |
---|
| 860 | + gtp_encap_disable_sock(sk0); |
---|
| 861 | + gtp_encap_disable_sock(sk1u); |
---|
874 | 862 | return -EINVAL; |
---|
875 | 863 | } |
---|
876 | 864 | } |
---|
.. | .. |
---|
935 | 923 | } |
---|
936 | 924 | } |
---|
937 | 925 | |
---|
938 | | -static int gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk, |
---|
939 | | - struct genl_info *info) |
---|
| 926 | +static struct pdp_ctx *gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk, |
---|
| 927 | + struct genl_info *info) |
---|
940 | 928 | { |
---|
941 | 929 | struct pdp_ctx *pctx, *pctx_tid = NULL; |
---|
942 | 930 | struct net_device *dev = gtp->dev; |
---|
.. | .. |
---|
963 | 951 | |
---|
964 | 952 | if (found) { |
---|
965 | 953 | if (info->nlhdr->nlmsg_flags & NLM_F_EXCL) |
---|
966 | | - return -EEXIST; |
---|
| 954 | + return ERR_PTR(-EEXIST); |
---|
967 | 955 | if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE) |
---|
968 | | - return -EOPNOTSUPP; |
---|
| 956 | + return ERR_PTR(-EOPNOTSUPP); |
---|
969 | 957 | |
---|
970 | 958 | if (pctx && pctx_tid) |
---|
971 | | - return -EEXIST; |
---|
| 959 | + return ERR_PTR(-EEXIST); |
---|
972 | 960 | if (!pctx) |
---|
973 | 961 | pctx = pctx_tid; |
---|
974 | 962 | |
---|
.. | .. |
---|
981 | 969 | netdev_dbg(dev, "GTPv1-U: update tunnel id = %x/%x (pdp %p)\n", |
---|
982 | 970 | pctx->u.v1.i_tei, pctx->u.v1.o_tei, pctx); |
---|
983 | 971 | |
---|
984 | | - return 0; |
---|
| 972 | + return pctx; |
---|
985 | 973 | |
---|
986 | 974 | } |
---|
987 | 975 | |
---|
988 | 976 | pctx = kmalloc(sizeof(*pctx), GFP_ATOMIC); |
---|
989 | 977 | if (pctx == NULL) |
---|
990 | | - return -ENOMEM; |
---|
| 978 | + return ERR_PTR(-ENOMEM); |
---|
991 | 979 | |
---|
992 | 980 | sock_hold(sk); |
---|
993 | 981 | pctx->sk = sk; |
---|
.. | .. |
---|
1025 | 1013 | break; |
---|
1026 | 1014 | } |
---|
1027 | 1015 | |
---|
1028 | | - return 0; |
---|
| 1016 | + return pctx; |
---|
1029 | 1017 | } |
---|
1030 | 1018 | |
---|
1031 | 1019 | static void pdp_context_free(struct rcu_head *head) |
---|
.. | .. |
---|
1043 | 1031 | call_rcu(&pctx->rcu_head, pdp_context_free); |
---|
1044 | 1032 | } |
---|
1045 | 1033 | |
---|
| 1034 | +static int gtp_tunnel_notify(struct pdp_ctx *pctx, u8 cmd, gfp_t allocation); |
---|
| 1035 | + |
---|
1046 | 1036 | static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info) |
---|
1047 | 1037 | { |
---|
1048 | 1038 | unsigned int version; |
---|
| 1039 | + struct pdp_ctx *pctx; |
---|
1049 | 1040 | struct gtp_dev *gtp; |
---|
1050 | 1041 | struct sock *sk; |
---|
1051 | 1042 | int err; |
---|
.. | .. |
---|
1075 | 1066 | } |
---|
1076 | 1067 | |
---|
1077 | 1068 | rtnl_lock(); |
---|
1078 | | - rcu_read_lock(); |
---|
1079 | 1069 | |
---|
1080 | 1070 | gtp = gtp_find_dev(sock_net(skb->sk), info->attrs); |
---|
1081 | 1071 | if (!gtp) { |
---|
.. | .. |
---|
1095 | 1085 | goto out_unlock; |
---|
1096 | 1086 | } |
---|
1097 | 1087 | |
---|
1098 | | - err = gtp_pdp_add(gtp, sk, info); |
---|
| 1088 | + pctx = gtp_pdp_add(gtp, sk, info); |
---|
| 1089 | + if (IS_ERR(pctx)) { |
---|
| 1090 | + err = PTR_ERR(pctx); |
---|
| 1091 | + } else { |
---|
| 1092 | + gtp_tunnel_notify(pctx, GTP_CMD_NEWPDP, GFP_KERNEL); |
---|
| 1093 | + err = 0; |
---|
| 1094 | + } |
---|
1099 | 1095 | |
---|
1100 | 1096 | out_unlock: |
---|
1101 | | - rcu_read_unlock(); |
---|
1102 | 1097 | rtnl_unlock(); |
---|
1103 | 1098 | return err; |
---|
1104 | 1099 | } |
---|
.. | .. |
---|
1166 | 1161 | netdev_dbg(pctx->dev, "GTPv1-U: deleting tunnel id = %x/%x (pdp %p)\n", |
---|
1167 | 1162 | pctx->u.v1.i_tei, pctx->u.v1.o_tei, pctx); |
---|
1168 | 1163 | |
---|
| 1164 | + gtp_tunnel_notify(pctx, GTP_CMD_DELPDP, GFP_ATOMIC); |
---|
1169 | 1165 | pdp_context_delete(pctx); |
---|
1170 | 1166 | |
---|
1171 | 1167 | out_unlock: |
---|
.. | .. |
---|
1174 | 1170 | } |
---|
1175 | 1171 | |
---|
1176 | 1172 | static struct genl_family gtp_genl_family; |
---|
| 1173 | + |
---|
| 1174 | +enum gtp_multicast_groups { |
---|
| 1175 | + GTP_GENL_MCGRP, |
---|
| 1176 | +}; |
---|
| 1177 | + |
---|
| 1178 | +static const struct genl_multicast_group gtp_genl_mcgrps[] = { |
---|
| 1179 | + [GTP_GENL_MCGRP] = { .name = GTP_GENL_MCGRP_NAME }, |
---|
| 1180 | +}; |
---|
1177 | 1181 | |
---|
1178 | 1182 | static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq, |
---|
1179 | 1183 | int flags, u32 type, struct pdp_ctx *pctx) |
---|
.. | .. |
---|
1210 | 1214 | nla_put_failure: |
---|
1211 | 1215 | genlmsg_cancel(skb, genlh); |
---|
1212 | 1216 | return -EMSGSIZE; |
---|
| 1217 | +} |
---|
| 1218 | + |
---|
| 1219 | +static int gtp_tunnel_notify(struct pdp_ctx *pctx, u8 cmd, gfp_t allocation) |
---|
| 1220 | +{ |
---|
| 1221 | + struct sk_buff *msg; |
---|
| 1222 | + int ret; |
---|
| 1223 | + |
---|
| 1224 | + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, allocation); |
---|
| 1225 | + if (!msg) |
---|
| 1226 | + return -ENOMEM; |
---|
| 1227 | + |
---|
| 1228 | + ret = gtp_genl_fill_info(msg, 0, 0, 0, cmd, pctx); |
---|
| 1229 | + if (ret < 0) { |
---|
| 1230 | + nlmsg_free(msg); |
---|
| 1231 | + return ret; |
---|
| 1232 | + } |
---|
| 1233 | + |
---|
| 1234 | + ret = genlmsg_multicast_netns(>p_genl_family, dev_net(pctx->dev), msg, |
---|
| 1235 | + 0, GTP_GENL_MCGRP, GFP_ATOMIC); |
---|
| 1236 | + return ret; |
---|
1213 | 1237 | } |
---|
1214 | 1238 | |
---|
1215 | 1239 | static int gtp_genl_get_pdp(struct sk_buff *skb, struct genl_info *info) |
---|
.. | .. |
---|
1310 | 1334 | [GTPA_O_TEI] = { .type = NLA_U32, }, |
---|
1311 | 1335 | }; |
---|
1312 | 1336 | |
---|
1313 | | -static const struct genl_ops gtp_genl_ops[] = { |
---|
| 1337 | +static const struct genl_small_ops gtp_genl_ops[] = { |
---|
1314 | 1338 | { |
---|
1315 | 1339 | .cmd = GTP_CMD_NEWPDP, |
---|
| 1340 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
1316 | 1341 | .doit = gtp_genl_new_pdp, |
---|
1317 | | - .policy = gtp_genl_policy, |
---|
1318 | 1342 | .flags = GENL_ADMIN_PERM, |
---|
1319 | 1343 | }, |
---|
1320 | 1344 | { |
---|
1321 | 1345 | .cmd = GTP_CMD_DELPDP, |
---|
| 1346 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
1322 | 1347 | .doit = gtp_genl_del_pdp, |
---|
1323 | | - .policy = gtp_genl_policy, |
---|
1324 | 1348 | .flags = GENL_ADMIN_PERM, |
---|
1325 | 1349 | }, |
---|
1326 | 1350 | { |
---|
1327 | 1351 | .cmd = GTP_CMD_GETPDP, |
---|
| 1352 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
1328 | 1353 | .doit = gtp_genl_get_pdp, |
---|
1329 | 1354 | .dumpit = gtp_genl_dump_pdp, |
---|
1330 | | - .policy = gtp_genl_policy, |
---|
1331 | 1355 | .flags = GENL_ADMIN_PERM, |
---|
1332 | 1356 | }, |
---|
1333 | 1357 | }; |
---|
.. | .. |
---|
1337 | 1361 | .version = 0, |
---|
1338 | 1362 | .hdrsize = 0, |
---|
1339 | 1363 | .maxattr = GTPA_MAX, |
---|
| 1364 | + .policy = gtp_genl_policy, |
---|
1340 | 1365 | .netnsok = true, |
---|
1341 | 1366 | .module = THIS_MODULE, |
---|
1342 | | - .ops = gtp_genl_ops, |
---|
1343 | | - .n_ops = ARRAY_SIZE(gtp_genl_ops), |
---|
| 1367 | + .small_ops = gtp_genl_ops, |
---|
| 1368 | + .n_small_ops = ARRAY_SIZE(gtp_genl_ops), |
---|
| 1369 | + .mcgrps = gtp_genl_mcgrps, |
---|
| 1370 | + .n_mcgrps = ARRAY_SIZE(gtp_genl_mcgrps), |
---|
1344 | 1371 | }; |
---|
1345 | 1372 | |
---|
1346 | 1373 | static int __net_init gtp_net_init(struct net *net) |
---|