History

sit: allow to configure 6rd tunnels via netlink

This patch add the support of 6RD tunnels management via netlink. Note that netdev_state_change() is now called when 6RD parameters are updated. 6RD parameters are updated only if there is at least one 6RD attribute.

Nicolas Dichtel committed 13 years ago

Commit e2f1f071 parent e4f67ad2 files · +128 −25Browse files

Unified · Split

2 files
  1. include/uapi/linux/if_tunnel.h +4 −0
  2. net/ipv6/sit.c +124 −25
include/uapi/linux/if_tunnel.h+4−0
@@ -49,6 +49,10 @@ enum { · 48 unmodified lines
49 IFLA_IPTUN_FLAGS,49 IFLA_IPTUN_FLAGS,
50 IFLA_IPTUN_PROTO,50 IFLA_IPTUN_PROTO,
51 IFLA_IPTUN_PMTUDISC,51 IFLA_IPTUN_PMTUDISC,
52 IFLA_IPTUN_6RD_PREFIX,
53 IFLA_IPTUN_6RD_RELAY_PREFIX,
54 IFLA_IPTUN_6RD_PREFIXLEN,
55 IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
52 __IFLA_IPTUN_MAX,56 __IFLA_IPTUN_MAX,
53};57};
54#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)58#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
net/ipv6/sit.c+124−25
@@ -936,6 +936,38 @@ static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p) · 935 unmodified lines
936 netdev_state_change(t->dev);936 netdev_state_change(t->dev);
937}937}
938 938
939#ifdef CONFIG_IPV6_SIT_6RD
940static int ipip6_tunnel_update_6rd(struct ip_tunnel *t,
941 struct ip_tunnel_6rd *ip6rd)
942{
943 struct in6_addr prefix;
944 __be32 relay_prefix;
945
946 if (ip6rd->relay_prefixlen > 32 ||
947 ip6rd->prefixlen + (32 - ip6rd->relay_prefixlen) > 64)
948 return -EINVAL;
949
950 ipv6_addr_prefix(&prefix, &ip6rd->prefix, ip6rd->prefixlen);
951 if (!ipv6_addr_equal(&prefix, &ip6rd->prefix))
952 return -EINVAL;
953 if (ip6rd->relay_prefixlen)
954 relay_prefix = ip6rd->relay_prefix &
955 htonl(0xffffffffUL <<
956 (32 - ip6rd->relay_prefixlen));
957 else
958 relay_prefix = 0;
959 if (relay_prefix != ip6rd->relay_prefix)
960 return -EINVAL;
961
962 t->ip6rd.prefix = prefix;
963 t->ip6rd.relay_prefix = relay_prefix;
964 t->ip6rd.prefixlen = ip6rd->prefixlen;
965 t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen;
966 netdev_state_change(t->dev);
967 return 0;
968}
969#endif
970
939static int971static int
940ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)972ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
941{973{
@@ -1105,31 +1137,9 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) · 163 unmodified lines
1105 t = netdev_priv(dev);1137 t = netdev_priv(dev);
1106 1138
1107 if (cmd != SIOCDEL6RD) {1139 if (cmd != SIOCDEL6RD) {
1108 struct in6_addr prefix;1140 err = ipip6_tunnel_update_6rd(t, &ip6rd);
1109 __be32 relay_prefix;1141 if (err < 0)
1110
1111 err = -EINVAL;
1112 if (ip6rd.relay_prefixlen > 32 ||
1113 ip6rd.prefixlen + (32 - ip6rd.relay_prefixlen) > 64)
1114 goto done;
1115
1116 ipv6_addr_prefix(&prefix, &ip6rd.prefix,
1117 ip6rd.prefixlen);
1118 if (!ipv6_addr_equal(&prefix, &ip6rd.prefix))
1119 goto done;1142 goto done;
1120 if (ip6rd.relay_prefixlen)
1121 relay_prefix = ip6rd.relay_prefix &
1122 htonl(0xffffffffUL <<
1123 (32 - ip6rd.relay_prefixlen));
1124 else
1125 relay_prefix = 0;
1126 if (relay_prefix != ip6rd.relay_prefix)
1127 goto done;
1128
1129 t->ip6rd.prefix = prefix;
1130 t->ip6rd.relay_prefix = relay_prefix;
1131 t->ip6rd.prefixlen = ip6rd.prefixlen;
1132 t->ip6rd.relay_prefixlen = ip6rd.relay_prefixlen;
1133 } else1143 } else
1134 ipip6_tunnel_clone_6rd(dev, sitn);1144 ipip6_tunnel_clone_6rd(dev, sitn);
1135 1145
@@ -1261,11 +1271,53 @@ static void ipip6_netlink_parms(struct nlattr *data[], · 125 unmodified lines
1261 parms->i_flags = nla_get_be16(data[IFLA_IPTUN_FLAGS]);1271 parms->i_flags = nla_get_be16(data[IFLA_IPTUN_FLAGS]);
1262}1272}
1263 1273
1274#ifdef CONFIG_IPV6_SIT_6RD
1275/* This function returns true when 6RD attributes are present in the nl msg */
1276static bool ipip6_netlink_6rd_parms(struct nlattr *data[],
1277 struct ip_tunnel_6rd *ip6rd)
1278{
1279 bool ret = false;
1280 memset(ip6rd, 0, sizeof(*ip6rd));
1281
1282 if (!data)
1283 return ret;
1284
1285 if (data[IFLA_IPTUN_6RD_PREFIX]) {
1286 ret = true;
1287 nla_memcpy(&ip6rd->prefix, data[IFLA_IPTUN_6RD_PREFIX],
1288 sizeof(struct in6_addr));
1289 }
1290
1291 if (data[IFLA_IPTUN_6RD_RELAY_PREFIX]) {
1292 ret = true;
1293 ip6rd->relay_prefix =
1294 nla_get_be32(data[IFLA_IPTUN_6RD_RELAY_PREFIX]);
1295 }
1296
1297 if (data[IFLA_IPTUN_6RD_PREFIXLEN]) {
1298 ret = true;
1299 ip6rd->prefixlen = nla_get_u16(data[IFLA_IPTUN_6RD_PREFIXLEN]);
1300 }
1301
1302 if (data[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]) {
1303 ret = true;
1304 ip6rd->relay_prefixlen =
1305 nla_get_u16(data[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
1306 }
1307
1308 return ret;
1309}
1310#endif
1311
1264static int ipip6_newlink(struct net *src_net, struct net_device *dev,1312static int ipip6_newlink(struct net *src_net, struct net_device *dev,
1265 struct nlattr *tb[], struct nlattr *data[])1313 struct nlattr *tb[], struct nlattr *data[])
1266{1314{
1267 struct net *net = dev_net(dev);1315 struct net *net = dev_net(dev);
1268 struct ip_tunnel *nt;1316 struct ip_tunnel *nt;
1317#ifdef CONFIG_IPV6_SIT_6RD
1318 struct ip_tunnel_6rd ip6rd;
1319#endif
1320 int err;
1269 1321
1270 nt = netdev_priv(dev);1322 nt = netdev_priv(dev);
1271 ipip6_netlink_parms(data, &nt->parms);1323 ipip6_netlink_parms(data, &nt->parms);
@@ -1273,7 +1325,16 @@ static int ipip6_newlink(struct net *src_net, struct net_device *dev, · 1 unmodified line
1273 if (ipip6_tunnel_locate(net, &nt->parms, 0))1325 if (ipip6_tunnel_locate(net, &nt->parms, 0))
1274 return -EEXIST;1326 return -EEXIST;
1275 1327
1276 return ipip6_tunnel_create(dev);1328 err = ipip6_tunnel_create(dev);
1329 if (err < 0)
1330 return err;
1331
1332#ifdef CONFIG_IPV6_SIT_6RD
1333 if (ipip6_netlink_6rd_parms(data, &ip6rd))
1334 err = ipip6_tunnel_update_6rd(nt, &ip6rd);
1335#endif
1336
1337 return err;
1277}1338}
1278 1339
1279static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[],1340static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[],
@@ -1283,6 +1344,9 @@ static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[], · 3 unmodified lines
1283 struct ip_tunnel_parm p;1344 struct ip_tunnel_parm p;
1284 struct net *net = dev_net(dev);1345 struct net *net = dev_net(dev);
1285 struct sit_net *sitn = net_generic(net, sit_net_id);1346 struct sit_net *sitn = net_generic(net, sit_net_id);
1347#ifdef CONFIG_IPV6_SIT_6RD
1348 struct ip_tunnel_6rd ip6rd;
1349#endif
1286 1350
1287 if (dev == sitn->fb_tunnel_dev)1351 if (dev == sitn->fb_tunnel_dev)
1288 return -EINVAL;1352 return -EINVAL;
@@ -1302,6 +1366,12 @@ static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[], · 13 unmodified lines
1302 t = netdev_priv(dev);1366 t = netdev_priv(dev);
1303 1367
1304 ipip6_tunnel_update(t, &p);1368 ipip6_tunnel_update(t, &p);
1369
1370#ifdef CONFIG_IPV6_SIT_6RD
1371 if (ipip6_netlink_6rd_parms(data, &ip6rd))
1372 return ipip6_tunnel_update_6rd(t, &ip6rd);
1373#endif
1374
1305 return 0;1375 return 0;
1306}1376}
1307 1377
@@ -1322,6 +1392,16 @@ static size_t ipip6_get_size(const struct net_device *dev) · 14 unmodified lines
1322 nla_total_size(1) +1392 nla_total_size(1) +
1323 /* IFLA_IPTUN_FLAGS */1393 /* IFLA_IPTUN_FLAGS */
1324 nla_total_size(2) +1394 nla_total_size(2) +
1395#ifdef CONFIG_IPV6_SIT_6RD
1396 /* IFLA_IPTUN_6RD_PREFIX */
1397 nla_total_size(sizeof(struct in6_addr)) +
1398 /* IFLA_IPTUN_6RD_RELAY_PREFIX */
1399 nla_total_size(4) +
1400 /* IFLA_IPTUN_6RD_PREFIXLEN */
1401 nla_total_size(2) +
1402 /* IFLA_IPTUN_6RD_RELAY_PREFIXLEN */
1403 nla_total_size(2) +
1404#endif
1325 0;1405 0;
1326}1406}
1327 1407
@@ -1339,6 +1419,19 @@ static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev) · 11 unmodified lines
1339 !!(parm->iph.frag_off & htons(IP_DF))) ||1419 !!(parm->iph.frag_off & htons(IP_DF))) ||
1340 nla_put_be16(skb, IFLA_IPTUN_FLAGS, parm->i_flags))1420 nla_put_be16(skb, IFLA_IPTUN_FLAGS, parm->i_flags))
1341 goto nla_put_failure;1421 goto nla_put_failure;
1422
1423#ifdef CONFIG_IPV6_SIT_6RD
1424 if (nla_put(skb, IFLA_IPTUN_6RD_PREFIX, sizeof(struct in6_addr),
1425 &tunnel->ip6rd.prefix) ||
1426 nla_put_be32(skb, IFLA_IPTUN_6RD_RELAY_PREFIX,
1427 tunnel->ip6rd.relay_prefix) ||
1428 nla_put_u16(skb, IFLA_IPTUN_6RD_PREFIXLEN,
1429 tunnel->ip6rd.prefixlen) ||
1430 nla_put_u16(skb, IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
1431 tunnel->ip6rd.relay_prefixlen))
1432 goto nla_put_failure;
1433#endif
1434
1342 return 0;1435 return 0;
1343 1436
1344nla_put_failure:1437nla_put_failure:
@@ -1353,6 +1446,12 @@ static const struct nla_policy ipip6_policy[IFLA_IPTUN_MAX + 1] = { · 8 unmodified lines
1353 [IFLA_IPTUN_TOS] = { .type = NLA_U8 },1446 [IFLA_IPTUN_TOS] = { .type = NLA_U8 },
1354 [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 },1447 [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 },
1355 [IFLA_IPTUN_FLAGS] = { .type = NLA_U16 },1448 [IFLA_IPTUN_FLAGS] = { .type = NLA_U16 },
1449#ifdef CONFIG_IPV6_SIT_6RD
1450 [IFLA_IPTUN_6RD_PREFIX] = { .len = sizeof(struct in6_addr) },
1451 [IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NLA_U32 },
1452 [IFLA_IPTUN_6RD_PREFIXLEN] = { .type = NLA_U16 },
1453 [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NLA_U16 },
1454#endif
1356};1455};
1357 1456
1358static struct rtnl_link_ops sit_link_ops __read_mostly = {1457static struct rtnl_link_ops sit_link_ops __read_mostly = {