struct ip_vs_conn *cp = NULL;
struct iphdr *iph = skb->nh.iph;
struct ip_vs_dest *dest;
- __u16 ports[2];
+ __u16 _ports[2], *pptr;
- if (skb_copy_bits(skb, iph->ihl*4, ports, sizeof(ports)) < 0)
+ pptr = skb_header_pointer(skb, iph->ihl*4,
+ sizeof(_ports), _ports);
+ if (pptr == NULL)
return NULL;
/*
* Persistent service
*/
if (svc->flags & IP_VS_SVC_F_PERSISTENT)
- return ip_vs_sched_persist(svc, skb, ports);
+ return ip_vs_sched_persist(svc, skb, pptr);
/*
* Non-persistent service
*/
- if (!svc->fwmark && ports[1] != svc->port) {
+ if (!svc->fwmark && pptr[1] != svc->port) {
if (!svc->port)
IP_VS_ERR("Schedule: port zero only supported "
"in persistent services, "
* Create a connection entry.
*/
cp = ip_vs_conn_new(iph->protocol,
- iph->saddr, ports[0],
- iph->daddr, ports[1],
- dest->addr, dest->port?dest->port:ports[1],
+ iph->saddr, pptr[0],
+ iph->daddr, pptr[1],
+ dest->addr, dest->port?dest->port:pptr[1],
0,
dest);
if (cp == NULL)
int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
struct ip_vs_protocol *pp)
{
- __u16 ports[2];
+ __u16 _ports[2], *pptr;
struct iphdr *iph = skb->nh.iph;
- if (skb_copy_bits(skb, iph->ihl*4, ports, sizeof(ports)) < 0) {
+ pptr = skb_header_pointer(skb, iph->ihl*4,
+ sizeof(_ports), _ports);
+ if (pptr == NULL) {
ip_vs_service_put(svc);
return NF_DROP;
}
/* create a new connection entry */
IP_VS_DBG(6, "ip_vs_leave: create a cache_bypass entry\n");
cp = ip_vs_conn_new(iph->protocol,
- iph->saddr, ports[0],
- iph->daddr, ports[1],
+ iph->saddr, pptr[0],
+ iph->daddr, pptr[1],
0, 0,
IP_VS_CONN_F_BYPASS,
NULL);
* listed in the ipvs table), pass the packets, because it is
* not ipvs job to decide to drop the packets.
*/
- if ((svc->port == FTPPORT) && (ports[1] != FTPPORT)) {
+ if ((svc->port == FTPPORT) && (pptr[1] != FTPPORT)) {
ip_vs_service_put(svc);
return NF_ACCEPT;
}
{
struct sk_buff *skb = *pskb;
struct iphdr *iph;
- struct icmphdr icmph;
- struct iphdr ciph; /* The ip header contained within the ICMP */
+ struct icmphdr _icmph, *ic;
+ struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */
struct ip_vs_conn *cp;
struct ip_vs_protocol *pp;
unsigned int offset, ihl, verdict;
iph = skb->nh.iph;
offset = ihl = iph->ihl * 4;
- if (skb_copy_bits(skb, offset, &icmph, sizeof(icmph)) < 0)
+ ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
+ if (ic == NULL)
return NF_DROP;
IP_VS_DBG(12, "Outgoing ICMP (%d,%d) %u.%u.%u.%u->%u.%u.%u.%u\n",
- icmph.type, ntohs(icmp_id(&icmph)),
+ ic->type, ntohs(icmp_id(ic)),
NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
/*
* this means that some packets will manage to get a long way
* down this stack and then be rejected, but that's life.
*/
- if ((icmph.type != ICMP_DEST_UNREACH) &&
- (icmph.type != ICMP_SOURCE_QUENCH) &&
- (icmph.type != ICMP_TIME_EXCEEDED)) {
+ if ((ic->type != ICMP_DEST_UNREACH) &&
+ (ic->type != ICMP_SOURCE_QUENCH) &&
+ (ic->type != ICMP_TIME_EXCEEDED)) {
*related = 0;
return NF_ACCEPT;
}
/* Now find the contained IP header */
- offset += sizeof(icmph);
- if (skb_copy_bits(skb, offset, &ciph, sizeof(ciph)) < 0)
+ offset += sizeof(_icmph);
+ cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+ if (cih == NULL)
return NF_ACCEPT; /* The packet looks wrong, ignore */
- pp = ip_vs_proto_get(ciph.protocol);
+ pp = ip_vs_proto_get(cih->protocol);
if (!pp)
return NF_ACCEPT;
/* Is the embedded protocol header present? */
- if (unlikely(ciph.frag_off & __constant_htons(IP_OFFSET) &&
+ if (unlikely(cih->frag_off & __constant_htons(IP_OFFSET) &&
pp->dont_defrag))
return NF_ACCEPT;
IP_VS_DBG_PKT(11, pp, skb, offset, "Checking outgoing ICMP for");
- offset += ciph.ihl * 4;
+ offset += cih->ihl * 4;
/* The embedded headers contain source and dest in reverse order */
- cp = pp->conn_out_get(skb, pp, &ciph, offset, 1);
+ cp = pp->conn_out_get(skb, pp, cih, offset, 1);
if (!cp)
return NF_ACCEPT;
goto out;
}
- if (IPPROTO_TCP == ciph.protocol || IPPROTO_UDP == ciph.protocol)
+ if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
offset += 2 * sizeof(__u16);
if (!ip_vs_make_skb_writable(pskb, offset))
goto out;
static inline int is_tcp_reset(const struct sk_buff *skb)
{
- struct tcphdr tcph;
+ struct tcphdr _tcph, *th;
- if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &tcph, sizeof(tcph)) < 0)
+ th = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+ sizeof(_tcph), &_tcph);
+ if (th == NULL)
return 0;
- return tcph.rst;
+ return th->rst;
}
/*
if (skb->nfcache & NFC_IPVS_PROPERTY)
return NF_ACCEPT;
- if (skb->ip_summed == CHECKSUM_HW) {
- if (skb_checksum_help(pskb, (out == NULL)))
- return NF_DROP;
- if (skb != *pskb)
- skb = *pskb;
- }
-
iph = skb->nh.iph;
if (unlikely(iph->protocol == IPPROTO_ICMP)) {
int related, verdict = ip_vs_out_icmp(pskb, &related);
if (sysctl_ip_vs_nat_icmp_send &&
(pp->protocol == IPPROTO_TCP ||
pp->protocol == IPPROTO_UDP)) {
- __u16 ports[2];
+ __u16 _ports[2], *pptr;
- if (skb_copy_bits(skb, ihl, ports, sizeof(ports)) < 0)
+ pptr = skb_header_pointer(skb, ihl,
+ sizeof(_ports), _ports);
+ if (pptr == NULL)
return NF_ACCEPT; /* Not for me */
if (ip_vs_lookup_real_service(iph->protocol,
- iph->saddr, ports[0])) {
+ iph->saddr, pptr[0])) {
/*
* Notify the real server: there is no
* existing entry if it is not RST
{
struct sk_buff *skb = *pskb;
struct iphdr *iph;
- struct icmphdr icmph;
- struct iphdr ciph; /* The ip header contained within the ICMP */
+ struct icmphdr _icmph, *ic;
+ struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */
struct ip_vs_conn *cp;
struct ip_vs_protocol *pp;
unsigned int offset, ihl, verdict;
iph = skb->nh.iph;
offset = ihl = iph->ihl * 4;
- if (skb_copy_bits(skb, offset, &icmph, sizeof(icmph)) < 0)
+ ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
+ if (ic == NULL)
return NF_DROP;
IP_VS_DBG(12, "Incoming ICMP (%d,%d) %u.%u.%u.%u->%u.%u.%u.%u\n",
- icmph.type, ntohs(icmp_id(&icmph)),
+ ic->type, ntohs(icmp_id(ic)),
NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
/*
* this means that some packets will manage to get a long way
* down this stack and then be rejected, but that's life.
*/
- if ((icmph.type != ICMP_DEST_UNREACH) &&
- (icmph.type != ICMP_SOURCE_QUENCH) &&
- (icmph.type != ICMP_TIME_EXCEEDED)) {
+ if ((ic->type != ICMP_DEST_UNREACH) &&
+ (ic->type != ICMP_SOURCE_QUENCH) &&
+ (ic->type != ICMP_TIME_EXCEEDED)) {
*related = 0;
return NF_ACCEPT;
}
/* Now find the contained IP header */
- offset += sizeof(icmph);
- if (skb_copy_bits(skb, offset, &ciph, sizeof(ciph)) < 0)
+ offset += sizeof(_icmph);
+ cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+ if (cih == NULL)
return NF_ACCEPT; /* The packet looks wrong, ignore */
- pp = ip_vs_proto_get(ciph.protocol);
+ pp = ip_vs_proto_get(cih->protocol);
if (!pp)
return NF_ACCEPT;
/* Is the embedded protocol header present? */
- if (unlikely(ciph.frag_off & __constant_htons(IP_OFFSET) &&
+ if (unlikely(cih->frag_off & __constant_htons(IP_OFFSET) &&
pp->dont_defrag))
return NF_ACCEPT;
IP_VS_DBG_PKT(11, pp, skb, offset, "Checking incoming ICMP for");
- offset += ciph.ihl * 4;
+ offset += cih->ihl * 4;
/* The embedded headers contain source and dest in reverse order */
- cp = pp->conn_in_get(skb, pp, &ciph, offset, 1);
+ cp = pp->conn_in_get(skb, pp, cih, offset, 1);
if (!cp)
return NF_ACCEPT;
/* do the statistics and put it back */
ip_vs_in_stats(cp, skb);
- if (IPPROTO_TCP == ciph.protocol || IPPROTO_UDP == ciph.protocol)
+ if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
offset += 2 * sizeof(__u16);
verdict = ip_vs_icmp_xmit(skb, cp, pp, offset);
/* do not touch skb anymore */
return NF_ACCEPT;
}
- if (skb->ip_summed == CHECKSUM_HW) {
- if (skb_checksum_help(pskb, (out == NULL)))
- return NF_DROP;
- if (skb != *pskb)
- skb = *pskb;
- }
-
iph = skb->nh.iph;
if (unlikely(iph->protocol == IPPROTO_ICMP)) {
int related, verdict = ip_vs_in_icmp(pskb, &related);