}
struct seg6_lwt {
- struct dst_cache cache;
+ struct dst_cache cache_input;
+ struct dst_cache cache_output;
+ struct in6_addr tunsrc;
struct seg6_iptunnel_encap tuninfo[];
};
memcpy(&slwt->tuninfo, tuninfo, tuninfo_len);
- goto free_dst_cache;
+ if (tb[SEG6_IPTUNNEL_SRC]) {
+ slwt->tunsrc = nla_get_in6_addr(tb[SEG6_IPTUNNEL_SRC]);
+
+ if (ipv6_addr_any(&slwt->tunsrc) ||
+ ipv6_addr_is_multicast(&slwt->tunsrc) ||
+ ipv6_addr_loopback(&slwt->tunsrc)) {
+ NL_SET_ERR_MSG(extack, "invalid tunsrc address");
+ err = -EINVAL;
++ goto err_destroy_output;
+ }
+ }
+
newts->type = LWTUNNEL_ENCAP_SEG6;
newts->flags |= LWTUNNEL_STATE_INPUT_REDIRECT;
return 0;
- free_dst_cache:
- dst_cache_destroy(&slwt->cache);
- free_lwt_state:
++err_destroy_output:
++ dst_cache_destroy(&slwt->cache_output);
+ err_destroy_input:
+ dst_cache_destroy(&slwt->cache_input);
+ err_free_newts:
kfree(newts);
return err;
}