|
|
@@ -18,22 +18,24 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
|
|
|
struct netns_ipvs *ipvs;
|
|
|
sctp_chunkhdr_t _schunkh, *sch;
|
|
|
sctp_sctphdr_t *sh, _sctph;
|
|
|
-
|
|
|
- if (ip_vs_iph_icmp(iph)) {
|
|
|
- /* TEMPORARY - do not schedule icmp yet */
|
|
|
- *verdict = NF_ACCEPT;
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- sh = skb_header_pointer(skb, iph->len, sizeof(_sctph), &_sctph);
|
|
|
- if (sh == NULL) {
|
|
|
- *verdict = NF_DROP;
|
|
|
- return 0;
|
|
|
+ __be16 _ports[2], *ports = NULL;
|
|
|
+
|
|
|
+ if (likely(!ip_vs_iph_icmp(iph))) {
|
|
|
+ sh = skb_header_pointer(skb, iph->len, sizeof(_sctph), &_sctph);
|
|
|
+ if (sh) {
|
|
|
+ sch = skb_header_pointer(
|
|
|
+ skb, iph->len + sizeof(sctp_sctphdr_t),
|
|
|
+ sizeof(_schunkh), &_schunkh);
|
|
|
+ if (sch && (sch->type == SCTP_CID_INIT ||
|
|
|
+ sysctl_sloppy_sctp(ipvs)))
|
|
|
+ ports = &sh->source;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ ports = skb_header_pointer(
|
|
|
+ skb, iph->len, sizeof(_ports), &_ports);
|
|
|
}
|
|
|
|
|
|
- sch = skb_header_pointer(skb, iph->len + sizeof(sctp_sctphdr_t),
|
|
|
- sizeof(_schunkh), &_schunkh);
|
|
|
- if (sch == NULL) {
|
|
|
+ if (!ports) {
|
|
|
*verdict = NF_DROP;
|
|
|
return 0;
|
|
|
}
|
|
|
@@ -41,9 +43,13 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
|
|
|
net = skb_net(skb);
|
|
|
ipvs = net_ipvs(net);
|
|
|
rcu_read_lock();
|
|
|
- if ((sch->type == SCTP_CID_INIT || sysctl_sloppy_sctp(ipvs)) &&
|
|
|
- (svc = ip_vs_service_find(net, af, skb->mark, iph->protocol,
|
|
|
- &iph->daddr, sh->dest))) {
|
|
|
+ if (likely(!ip_vs_iph_inverse(iph)))
|
|
|
+ svc = ip_vs_service_find(net, af, skb->mark, iph->protocol,
|
|
|
+ &iph->daddr, ports[1]);
|
|
|
+ else
|
|
|
+ svc = ip_vs_service_find(net, af, skb->mark, iph->protocol,
|
|
|
+ &iph->saddr, ports[0]);
|
|
|
+ if (svc) {
|
|
|
int ignored;
|
|
|
|
|
|
if (ip_vs_todrop(ipvs)) {
|