@@ -936,6 +936,38 @@ static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p)
936936 netdev_state_change (t -> dev );
937937}
938938
939+ #ifdef CONFIG_IPV6_SIT_6RD
940+ static 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+
939971static int
940972ipip6_tunnel_ioctl (struct net_device * dev , struct ifreq * ifr , int cmd )
941973{
@@ -1105,31 +1137,9 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
11051137 t = netdev_priv (dev );
11061138
11071139 if (cmd != SIOCDEL6RD ) {
1108- struct in6_addr prefix ;
1109- __be32 relay_prefix ;
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 ))
1140+ err = ipip6_tunnel_update_6rd (t , & ip6rd );
1141+ if (err < 0 )
11191142 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 ;
11331143 } else
11341144 ipip6_tunnel_clone_6rd (dev , sitn );
11351145
@@ -1261,19 +1271,70 @@ static void ipip6_netlink_parms(struct nlattr *data[],
12611271 parms -> i_flags = nla_get_be16 (data [IFLA_IPTUN_FLAGS ]);
12621272}
12631273
1274+ #ifdef CONFIG_IPV6_SIT_6RD
1275+ /* This function returns true when 6RD attributes are present in the nl msg */
1276+ static 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+
12641312static int ipip6_newlink (struct net * src_net , struct net_device * dev ,
12651313 struct nlattr * tb [], struct nlattr * data [])
12661314{
12671315 struct net * net = dev_net (dev );
12681316 struct ip_tunnel * nt ;
1317+ #ifdef CONFIG_IPV6_SIT_6RD
1318+ struct ip_tunnel_6rd ip6rd ;
1319+ #endif
1320+ int err ;
12691321
12701322 nt = netdev_priv (dev );
12711323 ipip6_netlink_parms (data , & nt -> parms );
12721324
12731325 if (ipip6_tunnel_locate (net , & nt -> parms , 0 ))
12741326 return - EEXIST ;
12751327
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 ;
12771338}
12781339
12791340static 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[],
12831344 struct ip_tunnel_parm p ;
12841345 struct net * net = dev_net (dev );
12851346 struct sit_net * sitn = net_generic (net , sit_net_id );
1347+ #ifdef CONFIG_IPV6_SIT_6RD
1348+ struct ip_tunnel_6rd ip6rd ;
1349+ #endif
12861350
12871351 if (dev == sitn -> fb_tunnel_dev )
12881352 return - EINVAL ;
@@ -1302,6 +1366,12 @@ static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[],
13021366 t = netdev_priv (dev );
13031367
13041368 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+
13051375 return 0 ;
13061376}
13071377
@@ -1322,6 +1392,16 @@ static size_t ipip6_get_size(const struct net_device *dev)
13221392 nla_total_size (1 ) +
13231393 /* IFLA_IPTUN_FLAGS */
13241394 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
13251405 0 ;
13261406}
13271407
@@ -1339,6 +1419,19 @@ static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev)
13391419 !!(parm -> iph .frag_off & htons (IP_DF ))) ||
13401420 nla_put_be16 (skb , IFLA_IPTUN_FLAGS , parm -> i_flags ))
13411421 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+
13421435 return 0 ;
13431436
13441437nla_put_failure :
@@ -1353,6 +1446,12 @@ static const struct nla_policy ipip6_policy[IFLA_IPTUN_MAX + 1] = {
13531446 [IFLA_IPTUN_TOS ] = { .type = NLA_U8 },
13541447 [IFLA_IPTUN_PMTUDISC ] = { .type = NLA_U8 },
13551448 [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
13561455};
13571456
13581457static struct rtnl_link_ops sit_link_ops __read_mostly = {
0 commit comments