Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (42 commits) [IPV6]: Consolidate the ip6_pol_route_(input|output) pair [TCP]: Make snd_cwnd_cnt 32-bit [TCP]: Update the /proc/net/tcp documentation [NETNS]: Don't panic on creating the namespace's loopback [NEIGH]: Ensure that pneigh_lookup is protected with RTNL [INET]: kmalloc+memset -> kzalloc in frag_alloc_queue [ISDN]: Fix compile with CONFIG_ISDN_X25 disabled. [IPV6]: Replace sk_buff ** with sk_buff * in input handlers [SELINUX]: Update for netfilter ->hook() arg changes. [INET]: Consolidate the xxx_put [INET]: Small cleanup for xxx_put after evictor consolidation [INET]: Consolidate the xxx_evictor [INET]: Consolidate the xxx_frag_destroy [INET]: Consolidate xxx_the secret_rebuild [INET]: Consolidate the xxx_frag_kill [INET]: Collect common frag sysctl variables together [INET]: Collect frag queues management objects together [INET]: Move common fields from frag_queues in one place. [TG3]: Fix performance regression on 5705. [ISDN]: Remove local copy of device name to make sure renames work. ...
This commit is contained in:
commit
a52cefc80f
@ -1,8 +1,9 @@
|
|||||||
This document describes the interfaces /proc/net/tcp and /proc/net/tcp6.
|
This document describes the interfaces /proc/net/tcp and /proc/net/tcp6.
|
||||||
|
Note that these interfaces are deprecated in favor of tcp_diag.
|
||||||
|
|
||||||
These /proc interfaces provide information about currently active TCP
|
These /proc interfaces provide information about currently active TCP
|
||||||
connections, and are implemented by tcp_get_info() in net/ipv4/tcp_ipv4.c and
|
connections, and are implemented by tcp4_seq_show() in net/ipv4/tcp_ipv4.c
|
||||||
tcp6_get_info() in net/ipv6/tcp_ipv6.c, respectively.
|
and tcp6_seq_show() in net/ipv6/tcp_ipv6.c, respectively.
|
||||||
|
|
||||||
It will first list all listening TCP sockets, and next list all established
|
It will first list all listening TCP sockets, and next list all established
|
||||||
TCP connections. A typical entry of /proc/net/tcp would look like this (split
|
TCP connections. A typical entry of /proc/net/tcp would look like this (split
|
||||||
|
@ -328,7 +328,7 @@ isdn_net_autohup(void)
|
|||||||
l->cps = (l->transcount * HZ) / (jiffies - last_jiffies);
|
l->cps = (l->transcount * HZ) / (jiffies - last_jiffies);
|
||||||
l->transcount = 0;
|
l->transcount = 0;
|
||||||
if (dev->net_verbose > 3)
|
if (dev->net_verbose > 3)
|
||||||
printk(KERN_DEBUG "%s: %d bogocps\n", l->name, l->cps);
|
printk(KERN_DEBUG "%s: %d bogocps\n", p->dev->name, l->cps);
|
||||||
if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) {
|
if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) {
|
||||||
anymore = 1;
|
anymore = 1;
|
||||||
l->huptimer++;
|
l->huptimer++;
|
||||||
@ -350,12 +350,12 @@ isdn_net_autohup(void)
|
|||||||
if (l->hupflags & ISDN_CHARGEHUP) {
|
if (l->hupflags & ISDN_CHARGEHUP) {
|
||||||
if (l->hupflags & ISDN_WAITCHARGE) {
|
if (l->hupflags & ISDN_WAITCHARGE) {
|
||||||
printk(KERN_DEBUG "isdn_net: Hupflags of %s are %X\n",
|
printk(KERN_DEBUG "isdn_net: Hupflags of %s are %X\n",
|
||||||
l->name, l->hupflags);
|
p->dev->name, l->hupflags);
|
||||||
isdn_net_hangup(p->dev);
|
isdn_net_hangup(p->dev);
|
||||||
} else if (time_after(jiffies, l->chargetime + l->chargeint)) {
|
} else if (time_after(jiffies, l->chargetime + l->chargeint)) {
|
||||||
printk(KERN_DEBUG
|
printk(KERN_DEBUG
|
||||||
"isdn_net: %s: chtime = %lu, chint = %d\n",
|
"isdn_net: %s: chtime = %lu, chint = %d\n",
|
||||||
l->name, l->chargetime, l->chargeint);
|
p->dev->name, l->chargetime, l->chargeint);
|
||||||
isdn_net_hangup(p->dev);
|
isdn_net_hangup(p->dev);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@ -442,8 +442,8 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
|
|||||||
#endif
|
#endif
|
||||||
isdn_net_lp_disconnected(lp);
|
isdn_net_lp_disconnected(lp);
|
||||||
isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
|
isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
|
||||||
printk(KERN_INFO "%s: remote hangup\n", lp->name);
|
printk(KERN_INFO "%s: remote hangup\n", p->dev->name);
|
||||||
printk(KERN_INFO "%s: Chargesum is %d\n", lp->name,
|
printk(KERN_INFO "%s: Chargesum is %d\n", p->dev->name,
|
||||||
lp->charge);
|
lp->charge);
|
||||||
isdn_net_unbind_channel(lp);
|
isdn_net_unbind_channel(lp);
|
||||||
return 1;
|
return 1;
|
||||||
@ -487,7 +487,7 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
|
|||||||
isdn_net_add_to_bundle(nd, lp);
|
isdn_net_add_to_bundle(nd, lp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printk(KERN_INFO "isdn_net: %s connected\n", lp->name);
|
printk(KERN_INFO "isdn_net: %s connected\n", p->dev->name);
|
||||||
/* If first Chargeinfo comes before B-Channel connect,
|
/* If first Chargeinfo comes before B-Channel connect,
|
||||||
* we correct the timestamp here.
|
* we correct the timestamp here.
|
||||||
*/
|
*/
|
||||||
@ -534,7 +534,7 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
|
|||||||
lp->hupflags |= ISDN_HAVECHARGE;
|
lp->hupflags |= ISDN_HAVECHARGE;
|
||||||
lp->chargetime = jiffies;
|
lp->chargetime = jiffies;
|
||||||
printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n",
|
printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n",
|
||||||
lp->name, lp->chargetime);
|
p->dev->name, lp->chargetime);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -565,7 +565,7 @@ isdn_net_dial(void)
|
|||||||
|
|
||||||
#ifdef ISDN_DEBUG_NET_DIAL
|
#ifdef ISDN_DEBUG_NET_DIAL
|
||||||
if (lp->dialstate)
|
if (lp->dialstate)
|
||||||
printk(KERN_DEBUG "%s: dialstate=%d\n", lp->name, lp->dialstate);
|
printk(KERN_DEBUG "%s: dialstate=%d\n", p->dev->name, lp->dialstate);
|
||||||
#endif
|
#endif
|
||||||
switch (lp->dialstate) {
|
switch (lp->dialstate) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -578,7 +578,7 @@ isdn_net_dial(void)
|
|||||||
lp->dial = lp->phone[1];
|
lp->dial = lp->phone[1];
|
||||||
if (!lp->dial) {
|
if (!lp->dial) {
|
||||||
printk(KERN_WARNING "%s: phone number deleted?\n",
|
printk(KERN_WARNING "%s: phone number deleted?\n",
|
||||||
lp->name);
|
p->dev->name);
|
||||||
isdn_net_hangup(p->dev);
|
isdn_net_hangup(p->dev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -632,13 +632,13 @@ isdn_net_dial(void)
|
|||||||
cmd.arg = lp->isdn_channel;
|
cmd.arg = lp->isdn_channel;
|
||||||
if (!lp->dial) {
|
if (!lp->dial) {
|
||||||
printk(KERN_WARNING "%s: phone number deleted?\n",
|
printk(KERN_WARNING "%s: phone number deleted?\n",
|
||||||
lp->name);
|
p->dev->name);
|
||||||
isdn_net_hangup(p->dev);
|
isdn_net_hangup(p->dev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!strncmp(lp->dial->num, "LEASED", strlen("LEASED"))) {
|
if (!strncmp(lp->dial->num, "LEASED", strlen("LEASED"))) {
|
||||||
lp->dialstate = 4;
|
lp->dialstate = 4;
|
||||||
printk(KERN_INFO "%s: Open leased line ...\n", lp->name);
|
printk(KERN_INFO "%s: Open leased line ...\n", p->dev->name);
|
||||||
} else {
|
} else {
|
||||||
if(lp->dialtimeout > 0)
|
if(lp->dialtimeout > 0)
|
||||||
if (time_after(jiffies, lp->dialstarted + lp->dialtimeout)) {
|
if (time_after(jiffies, lp->dialstarted + lp->dialtimeout)) {
|
||||||
@ -688,7 +688,7 @@ isdn_net_dial(void)
|
|||||||
dev->usage[i] |= ISDN_USAGE_OUTGOING;
|
dev->usage[i] |= ISDN_USAGE_OUTGOING;
|
||||||
isdn_info_update();
|
isdn_info_update();
|
||||||
}
|
}
|
||||||
printk(KERN_INFO "%s: dialing %d %s... %s\n", lp->name,
|
printk(KERN_INFO "%s: dialing %d %s... %s\n", p->dev->name,
|
||||||
lp->dialretry, cmd.parm.setup.phone,
|
lp->dialretry, cmd.parm.setup.phone,
|
||||||
(cmd.parm.setup.si1 == 1) ? "DOV" : "");
|
(cmd.parm.setup.si1 == 1) ? "DOV" : "");
|
||||||
lp->dtimer = 0;
|
lp->dtimer = 0;
|
||||||
@ -797,7 +797,7 @@ isdn_net_dial(void)
|
|||||||
*/
|
*/
|
||||||
if (lp->dtimer++ > lp->cbdelay)
|
if (lp->dtimer++ > lp->cbdelay)
|
||||||
{
|
{
|
||||||
printk(KERN_INFO "%s: hangup waiting for callback ...\n", lp->name);
|
printk(KERN_INFO "%s: hangup waiting for callback ...\n", p->dev->name);
|
||||||
lp->dtimer = 0;
|
lp->dtimer = 0;
|
||||||
lp->dialstate = 4;
|
lp->dialstate = 4;
|
||||||
cmd.driver = lp->isdn_device;
|
cmd.driver = lp->isdn_device;
|
||||||
@ -810,7 +810,7 @@ isdn_net_dial(void)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n",
|
printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n",
|
||||||
lp->dialstate, lp->name);
|
lp->dialstate, p->dev->name);
|
||||||
}
|
}
|
||||||
p = (isdn_net_dev *) p->next;
|
p = (isdn_net_dev *) p->next;
|
||||||
}
|
}
|
||||||
@ -836,11 +836,11 @@ isdn_net_hangup(struct net_device *d)
|
|||||||
if (slp->flags & ISDN_NET_CONNECTED) {
|
if (slp->flags & ISDN_NET_CONNECTED) {
|
||||||
printk(KERN_INFO
|
printk(KERN_INFO
|
||||||
"isdn_net: hang up slave %s before %s\n",
|
"isdn_net: hang up slave %s before %s\n",
|
||||||
slp->name, lp->name);
|
lp->slave->name, d->name);
|
||||||
isdn_net_hangup(lp->slave);
|
isdn_net_hangup(lp->slave);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name);
|
printk(KERN_INFO "isdn_net: local hangup %s\n", d->name);
|
||||||
#ifdef CONFIG_ISDN_PPP
|
#ifdef CONFIG_ISDN_PPP
|
||||||
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
|
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
|
||||||
isdn_ppp_free(lp);
|
isdn_ppp_free(lp);
|
||||||
@ -858,7 +858,7 @@ isdn_net_hangup(struct net_device *d)
|
|||||||
cmd.command = ISDN_CMD_HANGUP;
|
cmd.command = ISDN_CMD_HANGUP;
|
||||||
cmd.arg = lp->isdn_channel;
|
cmd.arg = lp->isdn_channel;
|
||||||
isdn_command(&cmd);
|
isdn_command(&cmd);
|
||||||
printk(KERN_INFO "%s: Chargesum is %d\n", lp->name, lp->charge);
|
printk(KERN_INFO "%s: Chargesum is %d\n", d->name, lp->charge);
|
||||||
isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
|
isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
|
||||||
}
|
}
|
||||||
isdn_net_unbind_channel(lp);
|
isdn_net_unbind_channel(lp);
|
||||||
@ -885,7 +885,7 @@ isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp)
|
|||||||
/* fall back to old isdn_net_log_packet method() */
|
/* fall back to old isdn_net_log_packet method() */
|
||||||
char * buf = skb->data;
|
char * buf = skb->data;
|
||||||
|
|
||||||
printk(KERN_DEBUG "isdn_net: protocol %04x is buggy, dev %s\n", skb->protocol, lp->name);
|
printk(KERN_DEBUG "isdn_net: protocol %04x is buggy, dev %s\n", skb->protocol, lp->netdev->dev->name);
|
||||||
p = buf;
|
p = buf;
|
||||||
proto = ETH_P_IP;
|
proto = ETH_P_IP;
|
||||||
switch (lp->p_encap) {
|
switch (lp->p_encap) {
|
||||||
@ -1023,7 +1023,7 @@ void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb)
|
|||||||
ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb);
|
ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb);
|
||||||
if (ret != len) {
|
if (ret != len) {
|
||||||
/* we should never get here */
|
/* we should never get here */
|
||||||
printk(KERN_WARNING "%s: HL driver queue full\n", lp->name);
|
printk(KERN_WARNING "%s: HL driver queue full\n", lp->netdev->dev->name);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1461,7 +1461,7 @@ isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
|||||||
mod_timer(&lp->cisco_timer, expires);
|
mod_timer(&lp->cisco_timer, expires);
|
||||||
printk(KERN_INFO "%s: Keepalive period set "
|
printk(KERN_INFO "%s: Keepalive period set "
|
||||||
"to %d seconds.\n",
|
"to %d seconds.\n",
|
||||||
lp->name, lp->cisco_keepalive_period);
|
dev->name, lp->cisco_keepalive_period);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1512,7 +1512,7 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
|
|||||||
lp->cisco_line_state = 0;
|
lp->cisco_line_state = 0;
|
||||||
printk (KERN_WARNING
|
printk (KERN_WARNING
|
||||||
"UPDOWN: Line protocol on Interface %s,"
|
"UPDOWN: Line protocol on Interface %s,"
|
||||||
" changed state to down\n", lp->name);
|
" changed state to down\n", lp->netdev->dev->name);
|
||||||
/* should stop routing higher-level data accross */
|
/* should stop routing higher-level data accross */
|
||||||
} else if ((!lp->cisco_line_state) &&
|
} else if ((!lp->cisco_line_state) &&
|
||||||
(myseq_diff >= 0) && (myseq_diff <= 2)) {
|
(myseq_diff >= 0) && (myseq_diff <= 2)) {
|
||||||
@ -1520,14 +1520,14 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
|
|||||||
lp->cisco_line_state = 1;
|
lp->cisco_line_state = 1;
|
||||||
printk (KERN_WARNING
|
printk (KERN_WARNING
|
||||||
"UPDOWN: Line protocol on Interface %s,"
|
"UPDOWN: Line protocol on Interface %s,"
|
||||||
" changed state to up\n", lp->name);
|
" changed state to up\n", lp->netdev->dev->name);
|
||||||
/* restart routing higher-level data accross */
|
/* restart routing higher-level data accross */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lp->cisco_debserint)
|
if (lp->cisco_debserint)
|
||||||
printk (KERN_DEBUG "%s: HDLC "
|
printk (KERN_DEBUG "%s: HDLC "
|
||||||
"myseq %lu, mineseen %lu%c, yourseen %lu, %s\n",
|
"myseq %lu, mineseen %lu%c, yourseen %lu, %s\n",
|
||||||
lp->name, last_cisco_myseq, lp->cisco_mineseen,
|
lp->netdev->dev->name, last_cisco_myseq, lp->cisco_mineseen,
|
||||||
((last_cisco_myseq == lp->cisco_mineseen) ? '*' : 040),
|
((last_cisco_myseq == lp->cisco_mineseen) ? '*' : 040),
|
||||||
lp->cisco_yourseq,
|
lp->cisco_yourseq,
|
||||||
((lp->cisco_line_state) ? "line up" : "line down"));
|
((lp->cisco_line_state) ? "line up" : "line down"));
|
||||||
@ -1682,7 +1682,7 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
|
|||||||
"remote ip: %d.%d.%d.%d, "
|
"remote ip: %d.%d.%d.%d, "
|
||||||
"local ip: %d.%d.%d.%d "
|
"local ip: %d.%d.%d.%d "
|
||||||
"mask: %d.%d.%d.%d\n",
|
"mask: %d.%d.%d.%d\n",
|
||||||
lp->name,
|
lp->netdev->dev->name,
|
||||||
HIPQUAD(addr),
|
HIPQUAD(addr),
|
||||||
HIPQUAD(local),
|
HIPQUAD(local),
|
||||||
HIPQUAD(mask));
|
HIPQUAD(mask));
|
||||||
@ -1690,7 +1690,7 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
|
|||||||
slarp_reply_out:
|
slarp_reply_out:
|
||||||
printk(KERN_INFO "%s: got invalid slarp "
|
printk(KERN_INFO "%s: got invalid slarp "
|
||||||
"reply (%d.%d.%d.%d/%d.%d.%d.%d) "
|
"reply (%d.%d.%d.%d/%d.%d.%d.%d) "
|
||||||
"- ignored\n", lp->name,
|
"- ignored\n", lp->netdev->dev->name,
|
||||||
HIPQUAD(addr), HIPQUAD(mask));
|
HIPQUAD(addr), HIPQUAD(mask));
|
||||||
break;
|
break;
|
||||||
case CISCO_SLARP_KEEPALIVE:
|
case CISCO_SLARP_KEEPALIVE:
|
||||||
@ -1701,7 +1701,8 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
|
|||||||
lp->cisco_last_slarp_in) {
|
lp->cisco_last_slarp_in) {
|
||||||
printk(KERN_DEBUG "%s: Keepalive period mismatch - "
|
printk(KERN_DEBUG "%s: Keepalive period mismatch - "
|
||||||
"is %d but should be %d.\n",
|
"is %d but should be %d.\n",
|
||||||
lp->name, period, lp->cisco_keepalive_period);
|
lp->netdev->dev->name, period,
|
||||||
|
lp->cisco_keepalive_period);
|
||||||
}
|
}
|
||||||
lp->cisco_last_slarp_in = jiffies;
|
lp->cisco_last_slarp_in = jiffies;
|
||||||
p += get_u32(p, &my_seq);
|
p += get_u32(p, &my_seq);
|
||||||
@ -1732,12 +1733,12 @@ isdn_net_ciscohdlck_receive(isdn_net_local *lp, struct sk_buff *skb)
|
|||||||
|
|
||||||
if (addr != CISCO_ADDR_UNICAST && addr != CISCO_ADDR_BROADCAST) {
|
if (addr != CISCO_ADDR_UNICAST && addr != CISCO_ADDR_BROADCAST) {
|
||||||
printk(KERN_WARNING "%s: Unknown Cisco addr 0x%02x\n",
|
printk(KERN_WARNING "%s: Unknown Cisco addr 0x%02x\n",
|
||||||
lp->name, addr);
|
lp->netdev->dev->name, addr);
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
if (ctrl != CISCO_CTRL) {
|
if (ctrl != CISCO_CTRL) {
|
||||||
printk(KERN_WARNING "%s: Unknown Cisco ctrl 0x%02x\n",
|
printk(KERN_WARNING "%s: Unknown Cisco ctrl 0x%02x\n",
|
||||||
lp->name, ctrl);
|
lp->netdev->dev->name, ctrl);
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1748,7 +1749,8 @@ isdn_net_ciscohdlck_receive(isdn_net_local *lp, struct sk_buff *skb)
|
|||||||
case CISCO_TYPE_CDP:
|
case CISCO_TYPE_CDP:
|
||||||
if (lp->cisco_debserint)
|
if (lp->cisco_debserint)
|
||||||
printk(KERN_DEBUG "%s: Received CDP packet. use "
|
printk(KERN_DEBUG "%s: Received CDP packet. use "
|
||||||
"\"no cdp enable\" on cisco.\n", lp->name);
|
"\"no cdp enable\" on cisco.\n",
|
||||||
|
lp->netdev->dev->name);
|
||||||
goto out_free;
|
goto out_free;
|
||||||
default:
|
default:
|
||||||
/* no special cisco protocol */
|
/* no special cisco protocol */
|
||||||
@ -1843,7 +1845,7 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
|
|||||||
};
|
};
|
||||||
#endif /* CONFIG_ISDN_X25 */
|
#endif /* CONFIG_ISDN_X25 */
|
||||||
printk(KERN_WARNING "%s: unknown encapsulation, dropping\n",
|
printk(KERN_WARNING "%s: unknown encapsulation, dropping\n",
|
||||||
lp->name);
|
lp->netdev->dev->name);
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2174,7 +2176,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
|
|||||||
wret = matchret;
|
wret = matchret;
|
||||||
#ifdef ISDN_DEBUG_NET_ICALL
|
#ifdef ISDN_DEBUG_NET_ICALL
|
||||||
printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",
|
printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",
|
||||||
lp->name, lp->msn, lp->flags, lp->dialstate);
|
p->dev->name, lp->msn, lp->flags, lp->dialstate);
|
||||||
#endif
|
#endif
|
||||||
if ((!matchret) && /* EAZ is matching */
|
if ((!matchret) && /* EAZ is matching */
|
||||||
(((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */
|
(((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */
|
||||||
@ -2277,7 +2279,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
|
|||||||
* */
|
* */
|
||||||
if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
|
if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
|
||||||
printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n",
|
printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n",
|
||||||
lp->name);
|
p->dev->name);
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -2286,7 +2288,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
|
|||||||
*/
|
*/
|
||||||
if (!isdn_net_device_started(p)) {
|
if (!isdn_net_device_started(p)) {
|
||||||
printk(KERN_INFO "%s: incoming call, interface down -> rejected\n",
|
printk(KERN_INFO "%s: incoming call, interface down -> rejected\n",
|
||||||
lp->name);
|
p->dev->name);
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
/* Interface is up, now see if it's a slave. If so, see if
|
/* Interface is up, now see if it's a slave. If so, see if
|
||||||
@ -2294,8 +2296,8 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
|
|||||||
*/
|
*/
|
||||||
if (lp->master) {
|
if (lp->master) {
|
||||||
isdn_net_local *mlp = (isdn_net_local *) lp->master->priv;
|
isdn_net_local *mlp = (isdn_net_local *) lp->master->priv;
|
||||||
printk(KERN_DEBUG "ICALLslv: %s\n", lp->name);
|
printk(KERN_DEBUG "ICALLslv: %s\n", p->dev->name);
|
||||||
printk(KERN_DEBUG "master=%s\n", mlp->name);
|
printk(KERN_DEBUG "master=%s\n", lp->master->name);
|
||||||
if (mlp->flags & ISDN_NET_CONNECTED) {
|
if (mlp->flags & ISDN_NET_CONNECTED) {
|
||||||
printk(KERN_DEBUG "master online\n");
|
printk(KERN_DEBUG "master online\n");
|
||||||
/* Master is online, find parent-slave (master if first slave) */
|
/* Master is online, find parent-slave (master if first slave) */
|
||||||
@ -2322,11 +2324,11 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
|
|||||||
* */
|
* */
|
||||||
if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
|
if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
|
||||||
printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n",
|
printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n",
|
||||||
lp->name);
|
p->dev->name);
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n",
|
printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n",
|
||||||
lp->name, nr, eaz);
|
p->dev->name, nr, eaz);
|
||||||
if (lp->phone[1]) {
|
if (lp->phone[1]) {
|
||||||
/* Grab a free ISDN-Channel */
|
/* Grab a free ISDN-Channel */
|
||||||
spin_lock_irqsave(&dev->lock, flags);
|
spin_lock_irqsave(&dev->lock, flags);
|
||||||
@ -2340,7 +2342,8 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
|
|||||||
lp->msn)
|
lp->msn)
|
||||||
) < 0) {
|
) < 0) {
|
||||||
|
|
||||||
printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n", lp->name);
|
printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n",
|
||||||
|
p->dev->name);
|
||||||
spin_unlock_irqrestore(&dev->lock, flags);
|
spin_unlock_irqrestore(&dev->lock, flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2361,11 +2364,12 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
|
|||||||
/* Initiate dialing by returning 2 or 4 */
|
/* Initiate dialing by returning 2 or 4 */
|
||||||
return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4;
|
return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4;
|
||||||
} else
|
} else
|
||||||
printk(KERN_WARNING "isdn_net: %s: No phone number\n", lp->name);
|
printk(KERN_WARNING "isdn_net: %s: No phone number\n",
|
||||||
|
p->dev->name);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_DEBUG "%s: call from %s -> %s accepted\n", lp->name, nr,
|
printk(KERN_DEBUG "%s: call from %s -> %s accepted\n",
|
||||||
eaz);
|
p->dev->name, nr, eaz);
|
||||||
/* if this interface is dialing, it does it probably on a different
|
/* if this interface is dialing, it does it probably on a different
|
||||||
device, so free this device */
|
device, so free this device */
|
||||||
if ((lp->dialstate == 4) || (lp->dialstate == 12)) {
|
if ((lp->dialstate == 4) || (lp->dialstate == 12)) {
|
||||||
@ -2424,7 +2428,7 @@ isdn_net_findif(char *name)
|
|||||||
isdn_net_dev *p = dev->netdev;
|
isdn_net_dev *p = dev->netdev;
|
||||||
|
|
||||||
while (p) {
|
while (p) {
|
||||||
if (!strcmp(p->local->name, name))
|
if (!strcmp(p->dev->name, name))
|
||||||
return p;
|
return p;
|
||||||
p = (isdn_net_dev *) p->next;
|
p = (isdn_net_dev *) p->next;
|
||||||
}
|
}
|
||||||
@ -2453,7 +2457,8 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
|
|||||||
lp->pre_device,
|
lp->pre_device,
|
||||||
lp->pre_channel,
|
lp->pre_channel,
|
||||||
lp->msn)) < 0) {
|
lp->msn)) < 0) {
|
||||||
printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name);
|
printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n",
|
||||||
|
lp->netdev->dev->name);
|
||||||
spin_unlock_irqrestore(&dev->lock, flags);
|
spin_unlock_irqrestore(&dev->lock, flags);
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
@ -2556,7 +2561,7 @@ isdn_net_new(char *name, struct net_device *master)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
name = " ";
|
return NULL;
|
||||||
if (!(netdev = kzalloc(sizeof(isdn_net_dev), GFP_KERNEL))) {
|
if (!(netdev = kzalloc(sizeof(isdn_net_dev), GFP_KERNEL))) {
|
||||||
printk(KERN_WARNING "isdn_net: Could not allocate net-device\n");
|
printk(KERN_WARNING "isdn_net: Could not allocate net-device\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2568,7 +2573,6 @@ isdn_net_new(char *name, struct net_device *master)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
netdev->local = netdev->dev->priv;
|
netdev->local = netdev->dev->priv;
|
||||||
strcpy(netdev->local->name, netdev->dev->name);
|
|
||||||
netdev->dev->init = isdn_net_init;
|
netdev->dev->init = isdn_net_init;
|
||||||
if (master) {
|
if (master) {
|
||||||
/* Device shall be a slave */
|
/* Device shall be a slave */
|
||||||
@ -2673,7 +2677,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
|
|||||||
#endif
|
#endif
|
||||||
if (isdn_net_device_started(p)) {
|
if (isdn_net_device_started(p)) {
|
||||||
printk(KERN_WARNING "%s: cannot change encap when if is up\n",
|
printk(KERN_WARNING "%s: cannot change encap when if is up\n",
|
||||||
lp->name);
|
p->dev->name);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_ISDN_X25
|
#ifdef CONFIG_ISDN_X25
|
||||||
@ -2698,7 +2702,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
|
|||||||
case ISDN_NET_ENCAP_SYNCPPP:
|
case ISDN_NET_ENCAP_SYNCPPP:
|
||||||
#ifndef CONFIG_ISDN_PPP
|
#ifndef CONFIG_ISDN_PPP
|
||||||
printk(KERN_WARNING "%s: SyncPPP support not configured\n",
|
printk(KERN_WARNING "%s: SyncPPP support not configured\n",
|
||||||
lp->name);
|
p->dev->name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
#else
|
#else
|
||||||
p->dev->type = ARPHRD_PPP; /* change ARP type */
|
p->dev->type = ARPHRD_PPP; /* change ARP type */
|
||||||
@ -2709,7 +2713,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
|
|||||||
case ISDN_NET_ENCAP_X25IFACE:
|
case ISDN_NET_ENCAP_X25IFACE:
|
||||||
#ifndef CONFIG_ISDN_X25
|
#ifndef CONFIG_ISDN_X25
|
||||||
printk(KERN_WARNING "%s: isdn-x25 support not configured\n",
|
printk(KERN_WARNING "%s: isdn-x25 support not configured\n",
|
||||||
p->local->name);
|
p->dev->name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
#else
|
#else
|
||||||
p->dev->type = ARPHRD_X25; /* change ARP type */
|
p->dev->type = ARPHRD_X25; /* change ARP type */
|
||||||
@ -2725,7 +2729,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
|
|||||||
break;
|
break;
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"%s: encapsulation protocol %d not supported\n",
|
"%s: encapsulation protocol %d not supported\n",
|
||||||
p->local->name, cfg->p_encap);
|
p->dev->name, cfg->p_encap);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (strlen(cfg->drvid)) {
|
if (strlen(cfg->drvid)) {
|
||||||
@ -2902,13 +2906,18 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
|
|||||||
cfg->pppbind = lp->pppbind;
|
cfg->pppbind = lp->pppbind;
|
||||||
cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1;
|
cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1;
|
||||||
cfg->dialwait = lp->dialwait / HZ;
|
cfg->dialwait = lp->dialwait / HZ;
|
||||||
if (lp->slave)
|
if (lp->slave) {
|
||||||
strcpy(cfg->slave, ((isdn_net_local *) lp->slave->priv)->name);
|
if (strlen(lp->slave->name) > 8)
|
||||||
else
|
strcpy(cfg->slave, "too-long");
|
||||||
|
else
|
||||||
|
strcpy(cfg->slave, lp->slave->name);
|
||||||
|
} else
|
||||||
cfg->slave[0] = '\0';
|
cfg->slave[0] = '\0';
|
||||||
if (lp->master)
|
if (lp->master) {
|
||||||
strcpy(cfg->master, ((isdn_net_local *) lp->master->priv)->name);
|
if (strlen(lp->master->name) > 8)
|
||||||
else
|
strcpy(cfg->master, "too-long");
|
||||||
|
strcpy(cfg->master, lp->master->name);
|
||||||
|
} else
|
||||||
cfg->master[0] = '\0';
|
cfg->master[0] = '\0';
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2978,7 +2987,8 @@ isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone __user *peer)
|
|||||||
isdn_net_dev *p = isdn_net_findif(phone->name);
|
isdn_net_dev *p = isdn_net_findif(phone->name);
|
||||||
int ch, dv, idx;
|
int ch, dv, idx;
|
||||||
|
|
||||||
if (!p) return -ENODEV;
|
if (!p)
|
||||||
|
return -ENODEV;
|
||||||
/*
|
/*
|
||||||
* Theoretical race: while this executes, the remote number might
|
* Theoretical race: while this executes, the remote number might
|
||||||
* become invalid (hang up) or change (new connection), resulting
|
* become invalid (hang up) or change (new connection), resulting
|
||||||
@ -2987,14 +2997,18 @@ isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone __user *peer)
|
|||||||
*/
|
*/
|
||||||
ch = p->local->isdn_channel;
|
ch = p->local->isdn_channel;
|
||||||
dv = p->local->isdn_device;
|
dv = p->local->isdn_device;
|
||||||
if(ch<0 && dv<0) return -ENOTCONN;
|
if(ch < 0 && dv < 0)
|
||||||
|
return -ENOTCONN;
|
||||||
idx = isdn_dc2minor(dv, ch);
|
idx = isdn_dc2minor(dv, ch);
|
||||||
if (idx<0) return -ENODEV;
|
if (idx <0 )
|
||||||
|
return -ENODEV;
|
||||||
/* for pre-bound channels, we need this extra check */
|
/* for pre-bound channels, we need this extra check */
|
||||||
if ( strncmp(dev->num[idx],"???",3) == 0 ) return -ENOTCONN;
|
if (strncmp(dev->num[idx], "???", 3) == 0)
|
||||||
strncpy(phone->phone,dev->num[idx],ISDN_MSNLEN);
|
return -ENOTCONN;
|
||||||
phone->outgoing=USG_OUTGOING(dev->usage[idx]);
|
strncpy(phone->phone, dev->num[idx], ISDN_MSNLEN);
|
||||||
if ( copy_to_user(peer,phone,sizeof(*peer)) ) return -EFAULT;
|
phone->outgoing = USG_OUTGOING(dev->usage[idx]);
|
||||||
|
if (copy_to_user(peer, phone, sizeof(*peer)))
|
||||||
|
return -EFAULT;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -3113,18 +3127,18 @@ isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
|
|||||||
dev->netdev = p->next;
|
dev->netdev = p->next;
|
||||||
if (p->local->slave) {
|
if (p->local->slave) {
|
||||||
/* If this interface has a slave, remove it also */
|
/* If this interface has a slave, remove it also */
|
||||||
char *slavename = ((isdn_net_local *) (p->local->slave->priv))->name;
|
char *slavename = p->local->slave->name;
|
||||||
isdn_net_dev *n = dev->netdev;
|
isdn_net_dev *n = dev->netdev;
|
||||||
q = NULL;
|
q = NULL;
|
||||||
while (n) {
|
while (n) {
|
||||||
if (!strcmp(n->local->name, slavename)) {
|
if (!strcmp(n->dev->name, slavename)) {
|
||||||
spin_unlock_irqrestore(&dev->lock, flags);
|
spin_unlock_irqrestore(&dev->lock, flags);
|
||||||
isdn_net_realrm(n, q);
|
isdn_net_realrm(n, q);
|
||||||
spin_lock_irqsave(&dev->lock, flags);
|
spin_lock_irqsave(&dev->lock, flags);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
q = n;
|
q = n;
|
||||||
n = (isdn_net_dev *) n->next;
|
n = (isdn_net_dev *)n->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&dev->lock, flags);
|
spin_unlock_irqrestore(&dev->lock, flags);
|
||||||
@ -3152,7 +3166,7 @@ isdn_net_rm(char *name)
|
|||||||
p = dev->netdev;
|
p = dev->netdev;
|
||||||
q = NULL;
|
q = NULL;
|
||||||
while (p) {
|
while (p) {
|
||||||
if (!strcmp(p->local->name, name)) {
|
if (!strcmp(p->dev->name, name)) {
|
||||||
spin_unlock_irqrestore(&dev->lock, flags);
|
spin_unlock_irqrestore(&dev->lock, flags);
|
||||||
return (isdn_net_realrm(p, q));
|
return (isdn_net_realrm(p, q));
|
||||||
}
|
}
|
||||||
|
@ -190,9 +190,11 @@ isdn_ppp_bind(isdn_net_local * lp)
|
|||||||
retval = -1;
|
retval = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
unit = isdn_ppp_if_get_unit(lp->name); /* get unit number from interface name .. ugly! */
|
/* get unit number from interface name .. ugly! */
|
||||||
|
unit = isdn_ppp_if_get_unit(lp->netdev->dev->name);
|
||||||
if (unit < 0) {
|
if (unit < 0) {
|
||||||
printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n", lp->name);
|
printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n",
|
||||||
|
lp->netdev->dev->name);
|
||||||
retval = -1;
|
retval = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -507,7 +509,8 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
|
|||||||
case PPPIOCGIFNAME:
|
case PPPIOCGIFNAME:
|
||||||
if(!lp)
|
if(!lp)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if ((r = set_arg(argp, lp->name, strlen(lp->name))))
|
if ((r = set_arg(argp, lp->netdev->dev->name,
|
||||||
|
strlen(lp->netdev->dev->name))))
|
||||||
return r;
|
return r;
|
||||||
break;
|
break;
|
||||||
case PPPIOCGMPFLAGS: /* get configuration flags */
|
case PPPIOCGMPFLAGS: /* get configuration flags */
|
||||||
|
@ -265,17 +265,16 @@ static __net_init int loopback_net_init(struct net *net)
|
|||||||
if (err)
|
if (err)
|
||||||
goto out_free_netdev;
|
goto out_free_netdev;
|
||||||
|
|
||||||
err = 0;
|
|
||||||
net->loopback_dev = dev;
|
net->loopback_dev = dev;
|
||||||
|
return 0;
|
||||||
|
|
||||||
out:
|
|
||||||
if (err)
|
|
||||||
panic("loopback: Failed to register netdevice: %d\n", err);
|
|
||||||
return err;
|
|
||||||
|
|
||||||
out_free_netdev:
|
out_free_netdev:
|
||||||
free_netdev(dev);
|
free_netdev(dev);
|
||||||
goto out;
|
out:
|
||||||
|
if (net == &init_net)
|
||||||
|
panic("loopback: Failed to register netdevice: %d\n", err);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __net_exit void loopback_net_exit(struct net *net)
|
static __net_exit void loopback_net_exit(struct net *net)
|
||||||
|
@ -6123,19 +6123,19 @@ static int __devinit niu_pci_probe_sprom(struct niu *np)
|
|||||||
val = nr64(ESPC_PHY_TYPE);
|
val = nr64(ESPC_PHY_TYPE);
|
||||||
switch (np->port) {
|
switch (np->port) {
|
||||||
case 0:
|
case 0:
|
||||||
val = (val & ESPC_PHY_TYPE_PORT0) >>
|
val8 = (val & ESPC_PHY_TYPE_PORT0) >>
|
||||||
ESPC_PHY_TYPE_PORT0_SHIFT;
|
ESPC_PHY_TYPE_PORT0_SHIFT;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
val = (val & ESPC_PHY_TYPE_PORT1) >>
|
val8 = (val & ESPC_PHY_TYPE_PORT1) >>
|
||||||
ESPC_PHY_TYPE_PORT1_SHIFT;
|
ESPC_PHY_TYPE_PORT1_SHIFT;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
val = (val & ESPC_PHY_TYPE_PORT2) >>
|
val8 = (val & ESPC_PHY_TYPE_PORT2) >>
|
||||||
ESPC_PHY_TYPE_PORT2_SHIFT;
|
ESPC_PHY_TYPE_PORT2_SHIFT;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
val = (val & ESPC_PHY_TYPE_PORT3) >>
|
val8 = (val & ESPC_PHY_TYPE_PORT3) >>
|
||||||
ESPC_PHY_TYPE_PORT3_SHIFT;
|
ESPC_PHY_TYPE_PORT3_SHIFT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -6143,9 +6143,9 @@ static int __devinit niu_pci_probe_sprom(struct niu *np)
|
|||||||
np->port);
|
np->port);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
niudbg(PROBE, "SPROM: PHY type %llx\n", (unsigned long long) val);
|
niudbg(PROBE, "SPROM: PHY type %x\n", val8);
|
||||||
|
|
||||||
switch (val) {
|
switch (val8) {
|
||||||
case ESPC_PHY_TYPE_1G_COPPER:
|
case ESPC_PHY_TYPE_1G_COPPER:
|
||||||
/* 1G copper, MII */
|
/* 1G copper, MII */
|
||||||
np->flags &= ~(NIU_FLAGS_FIBER |
|
np->flags &= ~(NIU_FLAGS_FIBER |
|
||||||
@ -6175,8 +6175,7 @@ static int __devinit niu_pci_probe_sprom(struct niu *np)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dev_err(np->device, PFX "Bogus SPROM phy type %llu\n",
|
dev_err(np->device, PFX "Bogus SPROM phy type %u\n", val8);
|
||||||
(unsigned long long) val);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6213,7 +6212,7 @@ static int __devinit niu_pci_probe_sprom(struct niu *np)
|
|||||||
val = nr64(ESPC_MOD_STR_LEN);
|
val = nr64(ESPC_MOD_STR_LEN);
|
||||||
niudbg(PROBE, "SPROM: MOD_STR_LEN[%llu]\n",
|
niudbg(PROBE, "SPROM: MOD_STR_LEN[%llu]\n",
|
||||||
(unsigned long long) val);
|
(unsigned long long) val);
|
||||||
if (val > 8 * 4)
|
if (val >= 8 * 4)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
for (i = 0; i < val; i += 4) {
|
for (i = 0; i < val; i += 4) {
|
||||||
@ -6229,7 +6228,7 @@ static int __devinit niu_pci_probe_sprom(struct niu *np)
|
|||||||
val = nr64(ESPC_BD_MOD_STR_LEN);
|
val = nr64(ESPC_BD_MOD_STR_LEN);
|
||||||
niudbg(PROBE, "SPROM: BD_MOD_STR_LEN[%llu]\n",
|
niudbg(PROBE, "SPROM: BD_MOD_STR_LEN[%llu]\n",
|
||||||
(unsigned long long) val);
|
(unsigned long long) val);
|
||||||
if (val > 4 * 4)
|
if (val >= 4 * 4)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
for (i = 0; i < val; i += 4) {
|
for (i = 0; i < val; i += 4) {
|
||||||
|
@ -64,8 +64,8 @@
|
|||||||
|
|
||||||
#define DRV_MODULE_NAME "tg3"
|
#define DRV_MODULE_NAME "tg3"
|
||||||
#define PFX DRV_MODULE_NAME ": "
|
#define PFX DRV_MODULE_NAME ": "
|
||||||
#define DRV_MODULE_VERSION "3.83"
|
#define DRV_MODULE_VERSION "3.84"
|
||||||
#define DRV_MODULE_RELDATE "October 10, 2007"
|
#define DRV_MODULE_RELDATE "October 12, 2007"
|
||||||
|
|
||||||
#define TG3_DEF_MAC_MODE 0
|
#define TG3_DEF_MAC_MODE 0
|
||||||
#define TG3_DEF_RX_MODE 0
|
#define TG3_DEF_RX_MODE 0
|
||||||
@ -5056,6 +5056,12 @@ static void tg3_restore_pci_state(struct tg3 *tp)
|
|||||||
|
|
||||||
pci_write_config_dword(tp->pdev, TG3PCI_COMMAND, tp->pci_cmd);
|
pci_write_config_dword(tp->pdev, TG3PCI_COMMAND, tp->pci_cmd);
|
||||||
|
|
||||||
|
if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
|
||||||
|
pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
|
||||||
|
tp->pci_cacheline_sz);
|
||||||
|
pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
|
||||||
|
tp->pci_lat_timer);
|
||||||
|
}
|
||||||
/* Make sure PCI-X relaxed ordering bit is clear. */
|
/* Make sure PCI-X relaxed ordering bit is clear. */
|
||||||
if (tp->pcix_cap) {
|
if (tp->pcix_cap) {
|
||||||
u16 pcix_cmd;
|
u16 pcix_cmd;
|
||||||
|
@ -107,7 +107,7 @@ struct __fdb_entry
|
|||||||
extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
|
extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
|
||||||
extern struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p,
|
extern struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p,
|
||||||
struct sk_buff *skb);
|
struct sk_buff *skb);
|
||||||
extern int (*br_should_route_hook)(struct sk_buff **pskb);
|
extern int (*br_should_route_hook)(struct sk_buff *skb);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -286,7 +286,6 @@ typedef struct {
|
|||||||
/* Local interface-data */
|
/* Local interface-data */
|
||||||
typedef struct isdn_net_local_s {
|
typedef struct isdn_net_local_s {
|
||||||
ulong magic;
|
ulong magic;
|
||||||
char name[10]; /* Name of device */
|
|
||||||
struct net_device_stats stats; /* Ethernet Statistics */
|
struct net_device_stats stats; /* Ethernet Statistics */
|
||||||
int isdn_device; /* Index to isdn-device */
|
int isdn_device; /* Index to isdn-device */
|
||||||
int isdn_channel; /* Index to isdn-channel */
|
int isdn_channel; /* Index to isdn-channel */
|
||||||
|
@ -51,7 +51,7 @@ struct sk_buff;
|
|||||||
struct net_device;
|
struct net_device;
|
||||||
|
|
||||||
typedef unsigned int nf_hookfn(unsigned int hooknum,
|
typedef unsigned int nf_hookfn(unsigned int hooknum,
|
||||||
struct sk_buff **skb,
|
struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *));
|
int (*okfn)(struct sk_buff *));
|
||||||
@ -183,7 +183,7 @@ void nf_log_packet(int pf,
|
|||||||
struct nf_loginfo *li,
|
struct nf_loginfo *li,
|
||||||
const char *fmt, ...);
|
const char *fmt, ...);
|
||||||
|
|
||||||
int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
|
int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
|
||||||
struct net_device *indev, struct net_device *outdev,
|
struct net_device *indev, struct net_device *outdev,
|
||||||
int (*okfn)(struct sk_buff *), int thresh);
|
int (*okfn)(struct sk_buff *), int thresh);
|
||||||
|
|
||||||
@ -195,7 +195,7 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
|
|||||||
* value indicates the packet has been consumed by the hook.
|
* value indicates the packet has been consumed by the hook.
|
||||||
*/
|
*/
|
||||||
static inline int nf_hook_thresh(int pf, unsigned int hook,
|
static inline int nf_hook_thresh(int pf, unsigned int hook,
|
||||||
struct sk_buff **pskb,
|
struct sk_buff *skb,
|
||||||
struct net_device *indev,
|
struct net_device *indev,
|
||||||
struct net_device *outdev,
|
struct net_device *outdev,
|
||||||
int (*okfn)(struct sk_buff *), int thresh,
|
int (*okfn)(struct sk_buff *), int thresh,
|
||||||
@ -207,14 +207,14 @@ static inline int nf_hook_thresh(int pf, unsigned int hook,
|
|||||||
if (list_empty(&nf_hooks[pf][hook]))
|
if (list_empty(&nf_hooks[pf][hook]))
|
||||||
return 1;
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
return nf_hook_slow(pf, hook, pskb, indev, outdev, okfn, thresh);
|
return nf_hook_slow(pf, hook, skb, indev, outdev, okfn, thresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int nf_hook(int pf, unsigned int hook, struct sk_buff **pskb,
|
static inline int nf_hook(int pf, unsigned int hook, struct sk_buff *skb,
|
||||||
struct net_device *indev, struct net_device *outdev,
|
struct net_device *indev, struct net_device *outdev,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
return nf_hook_thresh(pf, hook, pskb, indev, outdev, okfn, INT_MIN, 1);
|
return nf_hook_thresh(pf, hook, skb, indev, outdev, okfn, INT_MIN, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Activate hook; either okfn or kfree_skb called, unless a hook
|
/* Activate hook; either okfn or kfree_skb called, unless a hook
|
||||||
@ -241,13 +241,13 @@ static inline int nf_hook(int pf, unsigned int hook, struct sk_buff **pskb,
|
|||||||
|
|
||||||
#define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \
|
#define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \
|
||||||
({int __ret; \
|
({int __ret; \
|
||||||
if ((__ret=nf_hook_thresh(pf, hook, &(skb), indev, outdev, okfn, thresh, 1)) == 1)\
|
if ((__ret=nf_hook_thresh(pf, hook, (skb), indev, outdev, okfn, thresh, 1)) == 1)\
|
||||||
__ret = (okfn)(skb); \
|
__ret = (okfn)(skb); \
|
||||||
__ret;})
|
__ret;})
|
||||||
|
|
||||||
#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
|
#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
|
||||||
({int __ret; \
|
({int __ret; \
|
||||||
if ((__ret=nf_hook_thresh(pf, hook, &(skb), indev, outdev, okfn, INT_MIN, cond)) == 1)\
|
if ((__ret=nf_hook_thresh(pf, hook, (skb), indev, outdev, okfn, INT_MIN, cond)) == 1)\
|
||||||
__ret = (okfn)(skb); \
|
__ret = (okfn)(skb); \
|
||||||
__ret;})
|
__ret;})
|
||||||
|
|
||||||
@ -287,7 +287,7 @@ extern void nf_invalidate_cache(int pf);
|
|||||||
/* Call this before modifying an existing packet: ensures it is
|
/* Call this before modifying an existing packet: ensures it is
|
||||||
modifiable and linear to the point you care about (writable_len).
|
modifiable and linear to the point you care about (writable_len).
|
||||||
Returns true or false. */
|
Returns true or false. */
|
||||||
extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len);
|
extern int skb_make_writable(struct sk_buff *skb, unsigned int writable_len);
|
||||||
|
|
||||||
static inline void nf_csum_replace4(__sum16 *sum, __be32 from, __be32 to)
|
static inline void nf_csum_replace4(__sum16 *sum, __be32 from, __be32 to)
|
||||||
{
|
{
|
||||||
@ -317,7 +317,7 @@ struct nf_afinfo {
|
|||||||
unsigned int dataoff, u_int8_t protocol);
|
unsigned int dataoff, u_int8_t protocol);
|
||||||
void (*saveroute)(const struct sk_buff *skb,
|
void (*saveroute)(const struct sk_buff *skb,
|
||||||
struct nf_info *info);
|
struct nf_info *info);
|
||||||
int (*reroute)(struct sk_buff **skb,
|
int (*reroute)(struct sk_buff *skb,
|
||||||
const struct nf_info *info);
|
const struct nf_info *info);
|
||||||
int route_key_size;
|
int route_key_size;
|
||||||
};
|
};
|
||||||
@ -371,15 +371,15 @@ extern struct proc_dir_entry *proc_net_netfilter;
|
|||||||
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
|
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
|
||||||
#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
|
#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
|
||||||
static inline int nf_hook_thresh(int pf, unsigned int hook,
|
static inline int nf_hook_thresh(int pf, unsigned int hook,
|
||||||
struct sk_buff **pskb,
|
struct sk_buff *skb,
|
||||||
struct net_device *indev,
|
struct net_device *indev,
|
||||||
struct net_device *outdev,
|
struct net_device *outdev,
|
||||||
int (*okfn)(struct sk_buff *), int thresh,
|
int (*okfn)(struct sk_buff *), int thresh,
|
||||||
int cond)
|
int cond)
|
||||||
{
|
{
|
||||||
return okfn(*pskb);
|
return okfn(skb);
|
||||||
}
|
}
|
||||||
static inline int nf_hook(int pf, unsigned int hook, struct sk_buff **pskb,
|
static inline int nf_hook(int pf, unsigned int hook, struct sk_buff *skb,
|
||||||
struct net_device *indev, struct net_device *outdev,
|
struct net_device *indev, struct net_device *outdev,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#define _NF_CONNTRACK_AMANDA_H
|
#define _NF_CONNTRACK_AMANDA_H
|
||||||
/* AMANDA tracking. */
|
/* AMANDA tracking. */
|
||||||
|
|
||||||
extern unsigned int (*nf_nat_amanda_hook)(struct sk_buff **pskb,
|
extern unsigned int (*nf_nat_amanda_hook)(struct sk_buff *skb,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned int matchoff,
|
unsigned int matchoff,
|
||||||
unsigned int matchlen,
|
unsigned int matchlen,
|
||||||
|
@ -32,7 +32,7 @@ struct nf_conntrack_expect;
|
|||||||
|
|
||||||
/* For NAT to hook in when we find a packet which describes what other
|
/* For NAT to hook in when we find a packet which describes what other
|
||||||
* connection we should expect. */
|
* connection we should expect. */
|
||||||
extern unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb,
|
extern unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
enum nf_ct_ftp_type type,
|
enum nf_ct_ftp_type type,
|
||||||
unsigned int matchoff,
|
unsigned int matchoff,
|
||||||
|
@ -36,27 +36,27 @@ extern void nf_conntrack_h245_expect(struct nf_conn *new,
|
|||||||
struct nf_conntrack_expect *this);
|
struct nf_conntrack_expect *this);
|
||||||
extern void nf_conntrack_q931_expect(struct nf_conn *new,
|
extern void nf_conntrack_q931_expect(struct nf_conn *new,
|
||||||
struct nf_conntrack_expect *this);
|
struct nf_conntrack_expect *this);
|
||||||
extern int (*set_h245_addr_hook) (struct sk_buff **pskb,
|
extern int (*set_h245_addr_hook) (struct sk_buff *skb,
|
||||||
unsigned char **data, int dataoff,
|
unsigned char **data, int dataoff,
|
||||||
H245_TransportAddress *taddr,
|
H245_TransportAddress *taddr,
|
||||||
union nf_conntrack_address *addr,
|
union nf_conntrack_address *addr,
|
||||||
__be16 port);
|
__be16 port);
|
||||||
extern int (*set_h225_addr_hook) (struct sk_buff **pskb,
|
extern int (*set_h225_addr_hook) (struct sk_buff *skb,
|
||||||
unsigned char **data, int dataoff,
|
unsigned char **data, int dataoff,
|
||||||
TransportAddress *taddr,
|
TransportAddress *taddr,
|
||||||
union nf_conntrack_address *addr,
|
union nf_conntrack_address *addr,
|
||||||
__be16 port);
|
__be16 port);
|
||||||
extern int (*set_sig_addr_hook) (struct sk_buff **pskb,
|
extern int (*set_sig_addr_hook) (struct sk_buff *skb,
|
||||||
struct nf_conn *ct,
|
struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned char **data,
|
unsigned char **data,
|
||||||
TransportAddress *taddr, int count);
|
TransportAddress *taddr, int count);
|
||||||
extern int (*set_ras_addr_hook) (struct sk_buff **pskb,
|
extern int (*set_ras_addr_hook) (struct sk_buff *skb,
|
||||||
struct nf_conn *ct,
|
struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned char **data,
|
unsigned char **data,
|
||||||
TransportAddress *taddr, int count);
|
TransportAddress *taddr, int count);
|
||||||
extern int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb,
|
extern int (*nat_rtp_rtcp_hook) (struct sk_buff *skb,
|
||||||
struct nf_conn *ct,
|
struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned char **data, int dataoff,
|
unsigned char **data, int dataoff,
|
||||||
@ -64,24 +64,24 @@ extern int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb,
|
|||||||
__be16 port, __be16 rtp_port,
|
__be16 port, __be16 rtp_port,
|
||||||
struct nf_conntrack_expect *rtp_exp,
|
struct nf_conntrack_expect *rtp_exp,
|
||||||
struct nf_conntrack_expect *rtcp_exp);
|
struct nf_conntrack_expect *rtcp_exp);
|
||||||
extern int (*nat_t120_hook) (struct sk_buff **pskb, struct nf_conn *ct,
|
extern int (*nat_t120_hook) (struct sk_buff *skb, struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned char **data, int dataoff,
|
unsigned char **data, int dataoff,
|
||||||
H245_TransportAddress *taddr, __be16 port,
|
H245_TransportAddress *taddr, __be16 port,
|
||||||
struct nf_conntrack_expect *exp);
|
struct nf_conntrack_expect *exp);
|
||||||
extern int (*nat_h245_hook) (struct sk_buff **pskb, struct nf_conn *ct,
|
extern int (*nat_h245_hook) (struct sk_buff *skb, struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned char **data, int dataoff,
|
unsigned char **data, int dataoff,
|
||||||
TransportAddress *taddr, __be16 port,
|
TransportAddress *taddr, __be16 port,
|
||||||
struct nf_conntrack_expect *exp);
|
struct nf_conntrack_expect *exp);
|
||||||
extern int (*nat_callforwarding_hook) (struct sk_buff **pskb,
|
extern int (*nat_callforwarding_hook) (struct sk_buff *skb,
|
||||||
struct nf_conn *ct,
|
struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned char **data, int dataoff,
|
unsigned char **data, int dataoff,
|
||||||
TransportAddress *taddr,
|
TransportAddress *taddr,
|
||||||
__be16 port,
|
__be16 port,
|
||||||
struct nf_conntrack_expect *exp);
|
struct nf_conntrack_expect *exp);
|
||||||
extern int (*nat_q931_hook) (struct sk_buff **pskb, struct nf_conn *ct,
|
extern int (*nat_q931_hook) (struct sk_buff *skb, struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned char **data, TransportAddress *taddr,
|
unsigned char **data, TransportAddress *taddr,
|
||||||
int idx, __be16 port,
|
int idx, __be16 port,
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#define IRC_PORT 6667
|
#define IRC_PORT 6667
|
||||||
|
|
||||||
extern unsigned int (*nf_nat_irc_hook)(struct sk_buff **pskb,
|
extern unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned int matchoff,
|
unsigned int matchoff,
|
||||||
unsigned int matchlen,
|
unsigned int matchlen,
|
||||||
|
@ -301,13 +301,13 @@ struct nf_conn;
|
|||||||
struct nf_conntrack_expect;
|
struct nf_conntrack_expect;
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
(*nf_nat_pptp_hook_outbound)(struct sk_buff **pskb,
|
(*nf_nat_pptp_hook_outbound)(struct sk_buff *skb,
|
||||||
struct nf_conn *ct, enum ip_conntrack_info ctinfo,
|
struct nf_conn *ct, enum ip_conntrack_info ctinfo,
|
||||||
struct PptpControlHeader *ctlh,
|
struct PptpControlHeader *ctlh,
|
||||||
union pptp_ctrl_union *pptpReq);
|
union pptp_ctrl_union *pptpReq);
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
(*nf_nat_pptp_hook_inbound)(struct sk_buff **pskb,
|
(*nf_nat_pptp_hook_inbound)(struct sk_buff *skb,
|
||||||
struct nf_conn *ct, enum ip_conntrack_info ctinfo,
|
struct nf_conn *ct, enum ip_conntrack_info ctinfo,
|
||||||
struct PptpControlHeader *ctlh,
|
struct PptpControlHeader *ctlh,
|
||||||
union pptp_ctrl_union *pptpReq);
|
union pptp_ctrl_union *pptpReq);
|
||||||
|
@ -21,11 +21,11 @@ enum sip_header_pos {
|
|||||||
POS_SDP_HEADER,
|
POS_SDP_HEADER,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern unsigned int (*nf_nat_sip_hook)(struct sk_buff **pskb,
|
extern unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
struct nf_conn *ct,
|
struct nf_conn *ct,
|
||||||
const char **dptr);
|
const char **dptr);
|
||||||
extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff **pskb,
|
extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
struct nf_conntrack_expect *exp,
|
struct nf_conntrack_expect *exp,
|
||||||
const char *dptr);
|
const char *dptr);
|
||||||
|
@ -13,7 +13,7 @@ struct tftphdr {
|
|||||||
#define TFTP_OPCODE_ACK 4
|
#define TFTP_OPCODE_ACK 4
|
||||||
#define TFTP_OPCODE_ERROR 5
|
#define TFTP_OPCODE_ERROR 5
|
||||||
|
|
||||||
extern unsigned int (*nf_nat_tftp_hook)(struct sk_buff **pskb,
|
extern unsigned int (*nf_nat_tftp_hook)(struct sk_buff *skb,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
struct nf_conntrack_expect *exp);
|
struct nf_conntrack_expect *exp);
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ struct xt_target
|
|||||||
/* Returns verdict. Argument order changed since 2.6.9, as this
|
/* Returns verdict. Argument order changed since 2.6.9, as this
|
||||||
must now handle non-linear skbs, using skb_copy_bits and
|
must now handle non-linear skbs, using skb_copy_bits and
|
||||||
skb_ip_make_writable. */
|
skb_ip_make_writable. */
|
||||||
unsigned int (*target)(struct sk_buff **pskb,
|
unsigned int (*target)(struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
|
@ -287,7 +287,7 @@ struct arpt_error
|
|||||||
extern int arpt_register_table(struct arpt_table *table,
|
extern int arpt_register_table(struct arpt_table *table,
|
||||||
const struct arpt_replace *repl);
|
const struct arpt_replace *repl);
|
||||||
extern void arpt_unregister_table(struct arpt_table *table);
|
extern void arpt_unregister_table(struct arpt_table *table);
|
||||||
extern unsigned int arpt_do_table(struct sk_buff **pskb,
|
extern unsigned int arpt_do_table(struct sk_buff *skb,
|
||||||
unsigned int hook,
|
unsigned int hook,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
|
@ -237,7 +237,7 @@ struct ebt_target
|
|||||||
struct list_head list;
|
struct list_head list;
|
||||||
const char name[EBT_FUNCTION_MAXNAMELEN];
|
const char name[EBT_FUNCTION_MAXNAMELEN];
|
||||||
/* returns one of the standard verdicts */
|
/* returns one of the standard verdicts */
|
||||||
int (*target)(struct sk_buff **pskb, unsigned int hooknr,
|
int (*target)(struct sk_buff *skb, unsigned int hooknr,
|
||||||
const struct net_device *in, const struct net_device *out,
|
const struct net_device *in, const struct net_device *out,
|
||||||
const void *targetdata, unsigned int datalen);
|
const void *targetdata, unsigned int datalen);
|
||||||
/* 0 == let it in */
|
/* 0 == let it in */
|
||||||
@ -294,7 +294,7 @@ extern int ebt_register_watcher(struct ebt_watcher *watcher);
|
|||||||
extern void ebt_unregister_watcher(struct ebt_watcher *watcher);
|
extern void ebt_unregister_watcher(struct ebt_watcher *watcher);
|
||||||
extern int ebt_register_target(struct ebt_target *target);
|
extern int ebt_register_target(struct ebt_target *target);
|
||||||
extern void ebt_unregister_target(struct ebt_target *target);
|
extern void ebt_unregister_target(struct ebt_target *target);
|
||||||
extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff **pskb,
|
extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff *skb,
|
||||||
const struct net_device *in, const struct net_device *out,
|
const struct net_device *in, const struct net_device *out,
|
||||||
struct ebt_table *table);
|
struct ebt_table *table);
|
||||||
|
|
||||||
|
@ -75,8 +75,8 @@ enum nf_ip_hook_priorities {
|
|||||||
#define SO_ORIGINAL_DST 80
|
#define SO_ORIGINAL_DST 80
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
extern int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type);
|
extern int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type);
|
||||||
extern int ip_xfrm_me_harder(struct sk_buff **pskb);
|
extern int ip_xfrm_me_harder(struct sk_buff *skb);
|
||||||
extern __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
|
extern __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
|
||||||
unsigned int dataoff, u_int8_t protocol);
|
unsigned int dataoff, u_int8_t protocol);
|
||||||
#endif /*__KERNEL__*/
|
#endif /*__KERNEL__*/
|
||||||
|
@ -337,7 +337,7 @@ struct ipt_error
|
|||||||
.target.errorname = "ERROR", \
|
.target.errorname = "ERROR", \
|
||||||
}
|
}
|
||||||
|
|
||||||
extern unsigned int ipt_do_table(struct sk_buff **pskb,
|
extern unsigned int ipt_do_table(struct sk_buff *skb,
|
||||||
unsigned int hook,
|
unsigned int hook,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
|
@ -336,7 +336,7 @@ extern void ip6t_init(void) __init;
|
|||||||
extern int ip6t_register_table(struct xt_table *table,
|
extern int ip6t_register_table(struct xt_table *table,
|
||||||
const struct ip6t_replace *repl);
|
const struct ip6t_replace *repl);
|
||||||
extern void ip6t_unregister_table(struct xt_table *table);
|
extern void ip6t_unregister_table(struct xt_table *table);
|
||||||
extern unsigned int ip6t_do_table(struct sk_buff **pskb,
|
extern unsigned int ip6t_do_table(struct sk_buff *skb,
|
||||||
unsigned int hook,
|
unsigned int hook,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
|
@ -357,6 +357,7 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern void kfree_skbmem(struct sk_buff *skb);
|
extern void kfree_skbmem(struct sk_buff *skb);
|
||||||
|
extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src);
|
||||||
extern struct sk_buff *skb_clone(struct sk_buff *skb,
|
extern struct sk_buff *skb_clone(struct sk_buff *skb,
|
||||||
gfp_t priority);
|
gfp_t priority);
|
||||||
extern struct sk_buff *skb_copy(const struct sk_buff *skb,
|
extern struct sk_buff *skb_copy(const struct sk_buff *skb,
|
||||||
|
@ -315,7 +315,7 @@ struct tcp_sock {
|
|||||||
*/
|
*/
|
||||||
u32 snd_ssthresh; /* Slow start size threshold */
|
u32 snd_ssthresh; /* Slow start size threshold */
|
||||||
u32 snd_cwnd; /* Sending congestion window */
|
u32 snd_cwnd; /* Sending congestion window */
|
||||||
u16 snd_cwnd_cnt; /* Linear increase counter */
|
u32 snd_cwnd_cnt; /* Linear increase counter */
|
||||||
u32 snd_cwnd_clamp; /* Do not allow snd_cwnd to grow above this */
|
u32 snd_cwnd_clamp; /* Do not allow snd_cwnd to grow above this */
|
||||||
u32 snd_cwnd_used;
|
u32 snd_cwnd_used;
|
||||||
u32 snd_cwnd_stamp;
|
u32 snd_cwnd_stamp;
|
||||||
|
60
include/net/inet_frag.h
Normal file
60
include/net/inet_frag.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#ifndef __NET_FRAG_H__
|
||||||
|
#define __NET_FRAG_H__
|
||||||
|
|
||||||
|
struct inet_frag_queue {
|
||||||
|
struct hlist_node list;
|
||||||
|
struct list_head lru_list; /* lru list member */
|
||||||
|
spinlock_t lock;
|
||||||
|
atomic_t refcnt;
|
||||||
|
struct timer_list timer; /* when will this queue expire? */
|
||||||
|
struct sk_buff *fragments; /* list of received fragments */
|
||||||
|
ktime_t stamp;
|
||||||
|
int len; /* total length of orig datagram */
|
||||||
|
int meat;
|
||||||
|
__u8 last_in; /* first/last segment arrived? */
|
||||||
|
|
||||||
|
#define COMPLETE 4
|
||||||
|
#define FIRST_IN 2
|
||||||
|
#define LAST_IN 1
|
||||||
|
};
|
||||||
|
|
||||||
|
#define INETFRAGS_HASHSZ 64
|
||||||
|
|
||||||
|
struct inet_frags_ctl {
|
||||||
|
int high_thresh;
|
||||||
|
int low_thresh;
|
||||||
|
int timeout;
|
||||||
|
int secret_interval;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct inet_frags {
|
||||||
|
struct list_head lru_list;
|
||||||
|
struct hlist_head hash[INETFRAGS_HASHSZ];
|
||||||
|
rwlock_t lock;
|
||||||
|
u32 rnd;
|
||||||
|
int nqueues;
|
||||||
|
int qsize;
|
||||||
|
atomic_t mem;
|
||||||
|
struct timer_list secret_timer;
|
||||||
|
struct inet_frags_ctl *ctl;
|
||||||
|
|
||||||
|
unsigned int (*hashfn)(struct inet_frag_queue *);
|
||||||
|
void (*destructor)(struct inet_frag_queue *);
|
||||||
|
void (*skb_free)(struct sk_buff *);
|
||||||
|
};
|
||||||
|
|
||||||
|
void inet_frags_init(struct inet_frags *);
|
||||||
|
void inet_frags_fini(struct inet_frags *);
|
||||||
|
|
||||||
|
void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f);
|
||||||
|
void inet_frag_destroy(struct inet_frag_queue *q,
|
||||||
|
struct inet_frags *f, int *work);
|
||||||
|
int inet_frag_evictor(struct inet_frags *f);
|
||||||
|
|
||||||
|
static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f)
|
||||||
|
{
|
||||||
|
if (atomic_dec_and_test(&q->refcnt))
|
||||||
|
inet_frag_destroy(q, f, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -160,6 +160,7 @@ DECLARE_SNMP_STAT(struct ipstats_mib, ip_statistics);
|
|||||||
#define IP_INC_STATS(field) SNMP_INC_STATS(ip_statistics, field)
|
#define IP_INC_STATS(field) SNMP_INC_STATS(ip_statistics, field)
|
||||||
#define IP_INC_STATS_BH(field) SNMP_INC_STATS_BH(ip_statistics, field)
|
#define IP_INC_STATS_BH(field) SNMP_INC_STATS_BH(ip_statistics, field)
|
||||||
#define IP_INC_STATS_USER(field) SNMP_INC_STATS_USER(ip_statistics, field)
|
#define IP_INC_STATS_USER(field) SNMP_INC_STATS_USER(ip_statistics, field)
|
||||||
|
#define IP_ADD_STATS_BH(field, val) SNMP_ADD_STATS_BH(ip_statistics, field, val)
|
||||||
DECLARE_SNMP_STAT(struct linux_mib, net_statistics);
|
DECLARE_SNMP_STAT(struct linux_mib, net_statistics);
|
||||||
#define NET_INC_STATS(field) SNMP_INC_STATS(net_statistics, field)
|
#define NET_INC_STATS(field) SNMP_INC_STATS(net_statistics, field)
|
||||||
#define NET_INC_STATS_BH(field) SNMP_INC_STATS_BH(net_statistics, field)
|
#define NET_INC_STATS_BH(field) SNMP_INC_STATS_BH(net_statistics, field)
|
||||||
@ -177,10 +178,8 @@ extern int sysctl_ip_default_ttl;
|
|||||||
extern int sysctl_ip_nonlocal_bind;
|
extern int sysctl_ip_nonlocal_bind;
|
||||||
|
|
||||||
/* From ip_fragment.c */
|
/* From ip_fragment.c */
|
||||||
extern int sysctl_ipfrag_high_thresh;
|
struct inet_frags_ctl;
|
||||||
extern int sysctl_ipfrag_low_thresh;
|
extern struct inet_frags_ctl ip4_frags_ctl;
|
||||||
extern int sysctl_ipfrag_time;
|
|
||||||
extern int sysctl_ipfrag_secret_interval;
|
|
||||||
extern int sysctl_ipfrag_max_dist;
|
extern int sysctl_ipfrag_max_dist;
|
||||||
|
|
||||||
/* From inetpeer.c */
|
/* From inetpeer.c */
|
||||||
@ -332,9 +331,9 @@ enum ip_defrag_users
|
|||||||
IP_DEFRAG_VS_FWD
|
IP_DEFRAG_VS_FWD
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user);
|
int ip_defrag(struct sk_buff *skb, u32 user);
|
||||||
extern int ip_frag_nqueues;
|
int ip_frag_mem(void);
|
||||||
extern atomic_t ip_frag_mem;
|
int ip_frag_nqueues(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Functions provided by ip_forward.c
|
* Functions provided by ip_forward.c
|
||||||
|
@ -464,10 +464,10 @@ struct ip_vs_protocol {
|
|||||||
unsigned int proto_off,
|
unsigned int proto_off,
|
||||||
int inverse);
|
int inverse);
|
||||||
|
|
||||||
int (*snat_handler)(struct sk_buff **pskb,
|
int (*snat_handler)(struct sk_buff *skb,
|
||||||
struct ip_vs_protocol *pp, struct ip_vs_conn *cp);
|
struct ip_vs_protocol *pp, struct ip_vs_conn *cp);
|
||||||
|
|
||||||
int (*dnat_handler)(struct sk_buff **pskb,
|
int (*dnat_handler)(struct sk_buff *skb,
|
||||||
struct ip_vs_protocol *pp, struct ip_vs_conn *cp);
|
struct ip_vs_protocol *pp, struct ip_vs_conn *cp);
|
||||||
|
|
||||||
int (*csum_check)(struct sk_buff *skb, struct ip_vs_protocol *pp);
|
int (*csum_check)(struct sk_buff *skb, struct ip_vs_protocol *pp);
|
||||||
@ -654,11 +654,11 @@ struct ip_vs_app
|
|||||||
|
|
||||||
/* output hook: return false if can't linearize. diff set for TCP. */
|
/* output hook: return false if can't linearize. diff set for TCP. */
|
||||||
int (*pkt_out)(struct ip_vs_app *, struct ip_vs_conn *,
|
int (*pkt_out)(struct ip_vs_app *, struct ip_vs_conn *,
|
||||||
struct sk_buff **, int *diff);
|
struct sk_buff *, int *diff);
|
||||||
|
|
||||||
/* input hook: return false if can't linearize. diff set for TCP. */
|
/* input hook: return false if can't linearize. diff set for TCP. */
|
||||||
int (*pkt_in)(struct ip_vs_app *, struct ip_vs_conn *,
|
int (*pkt_in)(struct ip_vs_app *, struct ip_vs_conn *,
|
||||||
struct sk_buff **, int *diff);
|
struct sk_buff *, int *diff);
|
||||||
|
|
||||||
/* ip_vs_app initializer */
|
/* ip_vs_app initializer */
|
||||||
int (*init_conn)(struct ip_vs_app *, struct ip_vs_conn *);
|
int (*init_conn)(struct ip_vs_app *, struct ip_vs_conn *);
|
||||||
@ -832,8 +832,8 @@ register_ip_vs_app_inc(struct ip_vs_app *app, __u16 proto, __u16 port);
|
|||||||
extern int ip_vs_app_inc_get(struct ip_vs_app *inc);
|
extern int ip_vs_app_inc_get(struct ip_vs_app *inc);
|
||||||
extern void ip_vs_app_inc_put(struct ip_vs_app *inc);
|
extern void ip_vs_app_inc_put(struct ip_vs_app *inc);
|
||||||
|
|
||||||
extern int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff **pskb);
|
extern int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff *skb);
|
||||||
extern int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff **pskb);
|
extern int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff *skb);
|
||||||
extern int ip_vs_skb_replace(struct sk_buff *skb, gfp_t pri,
|
extern int ip_vs_skb_replace(struct sk_buff *skb, gfp_t pri,
|
||||||
char *o_buf, int o_len, char *n_buf, int n_len);
|
char *o_buf, int o_len, char *n_buf, int n_len);
|
||||||
extern int ip_vs_app_init(void);
|
extern int ip_vs_app_init(void);
|
||||||
@ -984,7 +984,6 @@ static inline char ip_vs_fwd_tag(struct ip_vs_conn *cp)
|
|||||||
return fwd;
|
return fwd;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int ip_vs_make_skb_writable(struct sk_buff **pskb, int len);
|
|
||||||
extern void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
extern void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
||||||
struct ip_vs_conn *cp, int dir);
|
struct ip_vs_conn *cp, int dir);
|
||||||
|
|
||||||
|
@ -120,12 +120,21 @@ extern int sysctl_mld_max_msf;
|
|||||||
SNMP_INC_STATS##modifier(statname##_statistics, (field)); \
|
SNMP_INC_STATS##modifier(statname##_statistics, (field)); \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
#define _DEVADD(statname, modifier, idev, field, val) \
|
||||||
|
({ \
|
||||||
|
struct inet6_dev *_idev = (idev); \
|
||||||
|
if (likely(_idev != NULL)) \
|
||||||
|
SNMP_ADD_STATS##modifier((_idev)->stats.statname, (field), (val)); \
|
||||||
|
SNMP_ADD_STATS##modifier(statname##_statistics, (field), (val));\
|
||||||
|
})
|
||||||
|
|
||||||
/* MIBs */
|
/* MIBs */
|
||||||
DECLARE_SNMP_STAT(struct ipstats_mib, ipv6_statistics);
|
DECLARE_SNMP_STAT(struct ipstats_mib, ipv6_statistics);
|
||||||
|
|
||||||
#define IP6_INC_STATS(idev,field) _DEVINC(ipv6, , idev, field)
|
#define IP6_INC_STATS(idev,field) _DEVINC(ipv6, , idev, field)
|
||||||
#define IP6_INC_STATS_BH(idev,field) _DEVINC(ipv6, _BH, idev, field)
|
#define IP6_INC_STATS_BH(idev,field) _DEVINC(ipv6, _BH, idev, field)
|
||||||
#define IP6_INC_STATS_USER(idev,field) _DEVINC(ipv6, _USER, idev, field)
|
#define IP6_INC_STATS_USER(idev,field) _DEVINC(ipv6, _USER, idev, field)
|
||||||
|
#define IP6_ADD_STATS_BH(idev,field,val) _DEVADD(ipv6, _BH, idev, field, val)
|
||||||
|
|
||||||
DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
|
DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
|
||||||
DECLARE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg_statistics);
|
DECLARE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg_statistics);
|
||||||
@ -240,7 +249,7 @@ extern int ip6_ra_control(struct sock *sk, int sel,
|
|||||||
void (*destructor)(struct sock *));
|
void (*destructor)(struct sock *));
|
||||||
|
|
||||||
|
|
||||||
extern int ipv6_parse_hopopts(struct sk_buff **skbp);
|
extern int ipv6_parse_hopopts(struct sk_buff *skb);
|
||||||
|
|
||||||
extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt);
|
extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt);
|
||||||
extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
|
extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
|
||||||
@ -252,8 +261,8 @@ struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
|
|||||||
|
|
||||||
extern int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb);
|
extern int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb);
|
||||||
|
|
||||||
extern int ip6_frag_nqueues;
|
int ip6_frag_nqueues(void);
|
||||||
extern atomic_t ip6_frag_mem;
|
int ip6_frag_mem(void);
|
||||||
|
|
||||||
#define IPV6_FRAG_TIMEOUT (60*HZ) /* 60 seconds */
|
#define IPV6_FRAG_TIMEOUT (60*HZ) /* 60 seconds */
|
||||||
|
|
||||||
@ -565,10 +574,8 @@ extern int inet6_hash_connect(struct inet_timewait_death_row *death_row,
|
|||||||
/*
|
/*
|
||||||
* reassembly.c
|
* reassembly.c
|
||||||
*/
|
*/
|
||||||
extern int sysctl_ip6frag_high_thresh;
|
struct inet_frags_ctl;
|
||||||
extern int sysctl_ip6frag_low_thresh;
|
extern struct inet_frags_ctl ip6_frags_ctl;
|
||||||
extern int sysctl_ip6frag_time;
|
|
||||||
extern int sysctl_ip6frag_secret_interval;
|
|
||||||
|
|
||||||
extern const struct proto_ops inet6_stream_ops;
|
extern const struct proto_ops inet6_stream_ops;
|
||||||
extern const struct proto_ops inet6_dgram_ops;
|
extern const struct proto_ops inet6_dgram_ops;
|
||||||
|
@ -15,8 +15,7 @@ extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
|
|||||||
struct net_device *out,
|
struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *));
|
int (*okfn)(struct sk_buff *));
|
||||||
|
|
||||||
extern unsigned int nf_ct_frag6_timeout;
|
struct inet_frags_ctl;
|
||||||
extern unsigned int nf_ct_frag6_low_thresh;
|
extern struct inet_frags_ctl nf_frags_ctl;
|
||||||
extern unsigned int nf_ct_frag6_high_thresh;
|
|
||||||
|
|
||||||
#endif /* _NF_CONNTRACK_IPV6_H*/
|
#endif /* _NF_CONNTRACK_IPV6_H*/
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
of connection tracking. */
|
of connection tracking. */
|
||||||
extern unsigned int nf_conntrack_in(int pf,
|
extern unsigned int nf_conntrack_in(int pf,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
struct sk_buff **pskb);
|
struct sk_buff *skb);
|
||||||
|
|
||||||
extern int nf_conntrack_init(void);
|
extern int nf_conntrack_init(void);
|
||||||
extern void nf_conntrack_cleanup(void);
|
extern void nf_conntrack_cleanup(void);
|
||||||
@ -60,17 +60,17 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
|
|||||||
extern struct nf_conntrack_tuple_hash *
|
extern struct nf_conntrack_tuple_hash *
|
||||||
nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple);
|
nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple);
|
||||||
|
|
||||||
extern int __nf_conntrack_confirm(struct sk_buff **pskb);
|
extern int __nf_conntrack_confirm(struct sk_buff *skb);
|
||||||
|
|
||||||
/* Confirm a connection: returns NF_DROP if packet must be dropped. */
|
/* Confirm a connection: returns NF_DROP if packet must be dropped. */
|
||||||
static inline int nf_conntrack_confirm(struct sk_buff **pskb)
|
static inline int nf_conntrack_confirm(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct nf_conn *ct = (struct nf_conn *)(*pskb)->nfct;
|
struct nf_conn *ct = (struct nf_conn *)skb->nfct;
|
||||||
int ret = NF_ACCEPT;
|
int ret = NF_ACCEPT;
|
||||||
|
|
||||||
if (ct) {
|
if (ct) {
|
||||||
if (!nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct))
|
if (!nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct))
|
||||||
ret = __nf_conntrack_confirm(pskb);
|
ret = __nf_conntrack_confirm(skb);
|
||||||
nf_ct_deliver_cached_events(ct);
|
nf_ct_deliver_cached_events(ct);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -29,7 +29,7 @@ struct nf_conntrack_helper
|
|||||||
|
|
||||||
/* Function to call when data passes; return verdict, or -1 to
|
/* Function to call when data passes; return verdict, or -1 to
|
||||||
invalidate. */
|
invalidate. */
|
||||||
int (*help)(struct sk_buff **pskb,
|
int (*help)(struct sk_buff *skb,
|
||||||
unsigned int protoff,
|
unsigned int protoff,
|
||||||
struct nf_conn *ct,
|
struct nf_conn *ct,
|
||||||
enum ip_conntrack_info conntrackinfo);
|
enum ip_conntrack_info conntrackinfo);
|
||||||
|
@ -10,12 +10,12 @@
|
|||||||
extern unsigned int nf_nat_packet(struct nf_conn *ct,
|
extern unsigned int nf_nat_packet(struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
struct sk_buff **pskb);
|
struct sk_buff *skb);
|
||||||
|
|
||||||
extern int nf_nat_icmp_reply_translation(struct nf_conn *ct,
|
extern int nf_nat_icmp_reply_translation(struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
struct sk_buff **pskb);
|
struct sk_buff *skb);
|
||||||
|
|
||||||
static inline int nf_nat_initialized(struct nf_conn *ct,
|
static inline int nf_nat_initialized(struct nf_conn *ct,
|
||||||
enum nf_nat_manip_type manip)
|
enum nf_nat_manip_type manip)
|
||||||
|
@ -7,21 +7,21 @@
|
|||||||
struct sk_buff;
|
struct sk_buff;
|
||||||
|
|
||||||
/* These return true or false. */
|
/* These return true or false. */
|
||||||
extern int nf_nat_mangle_tcp_packet(struct sk_buff **skb,
|
extern int nf_nat_mangle_tcp_packet(struct sk_buff *skb,
|
||||||
struct nf_conn *ct,
|
struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned int match_offset,
|
unsigned int match_offset,
|
||||||
unsigned int match_len,
|
unsigned int match_len,
|
||||||
const char *rep_buffer,
|
const char *rep_buffer,
|
||||||
unsigned int rep_len);
|
unsigned int rep_len);
|
||||||
extern int nf_nat_mangle_udp_packet(struct sk_buff **skb,
|
extern int nf_nat_mangle_udp_packet(struct sk_buff *skb,
|
||||||
struct nf_conn *ct,
|
struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned int match_offset,
|
unsigned int match_offset,
|
||||||
unsigned int match_len,
|
unsigned int match_len,
|
||||||
const char *rep_buffer,
|
const char *rep_buffer,
|
||||||
unsigned int rep_len);
|
unsigned int rep_len);
|
||||||
extern int nf_nat_seq_adjust(struct sk_buff **pskb,
|
extern int nf_nat_seq_adjust(struct sk_buff *skb,
|
||||||
struct nf_conn *ct,
|
struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo);
|
enum ip_conntrack_info ctinfo);
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ struct nf_nat_protocol
|
|||||||
|
|
||||||
/* Translate a packet to the target according to manip type.
|
/* Translate a packet to the target according to manip type.
|
||||||
Return true if succeeded. */
|
Return true if succeeded. */
|
||||||
int (*manip_pkt)(struct sk_buff **pskb,
|
int (*manip_pkt)(struct sk_buff *skb,
|
||||||
unsigned int iphdroff,
|
unsigned int iphdroff,
|
||||||
const struct nf_conntrack_tuple *tuple,
|
const struct nf_conntrack_tuple *tuple,
|
||||||
enum nf_nat_manip_type maniptype);
|
enum nf_nat_manip_type maniptype);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
extern int nf_nat_rule_init(void) __init;
|
extern int nf_nat_rule_init(void) __init;
|
||||||
extern void nf_nat_rule_cleanup(void);
|
extern void nf_nat_rule_cleanup(void);
|
||||||
extern int nf_nat_rule_find(struct sk_buff **pskb,
|
extern int nf_nat_rule_find(struct sk_buff *skb,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
|
@ -45,7 +45,7 @@ struct net_protocol {
|
|||||||
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
|
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
|
||||||
struct inet6_protocol
|
struct inet6_protocol
|
||||||
{
|
{
|
||||||
int (*handler)(struct sk_buff **skb);
|
int (*handler)(struct sk_buff *skb);
|
||||||
|
|
||||||
void (*err_handler)(struct sk_buff *skb,
|
void (*err_handler)(struct sk_buff *skb,
|
||||||
struct inet6_skb_parm *opt,
|
struct inet6_skb_parm *opt,
|
||||||
|
@ -1051,7 +1051,7 @@ extern int xfrm4_output(struct sk_buff *skb);
|
|||||||
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
|
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
|
||||||
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
|
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
|
||||||
extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi);
|
extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi);
|
||||||
extern int xfrm6_rcv(struct sk_buff **pskb);
|
extern int xfrm6_rcv(struct sk_buff *skb);
|
||||||
extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
|
extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
|
||||||
xfrm_address_t *saddr, u8 proto);
|
xfrm_address_t *saddr, u8 proto);
|
||||||
extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family);
|
extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family);
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "br_private.h"
|
#include "br_private.h"
|
||||||
|
|
||||||
int (*br_should_route_hook) (struct sk_buff **pskb) = NULL;
|
int (*br_should_route_hook)(struct sk_buff *skb);
|
||||||
|
|
||||||
static struct llc_sap *br_stp_sap;
|
static struct llc_sap *br_stp_sap;
|
||||||
|
|
||||||
|
@ -126,6 +126,10 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
|
|||||||
if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
|
if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
|
||||||
goto drop;
|
goto drop;
|
||||||
|
|
||||||
|
skb = skb_share_check(skb, GFP_ATOMIC);
|
||||||
|
if (!skb)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (unlikely(is_link_local(dest))) {
|
if (unlikely(is_link_local(dest))) {
|
||||||
/* Pause frames shouldn't be passed up by driver anyway */
|
/* Pause frames shouldn't be passed up by driver anyway */
|
||||||
if (skb->protocol == htons(ETH_P_PAUSE))
|
if (skb->protocol == htons(ETH_P_PAUSE))
|
||||||
@ -145,7 +149,7 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
|
|||||||
case BR_STATE_FORWARDING:
|
case BR_STATE_FORWARDING:
|
||||||
|
|
||||||
if (br_should_route_hook) {
|
if (br_should_route_hook) {
|
||||||
if (br_should_route_hook(&skb))
|
if (br_should_route_hook(skb))
|
||||||
return skb;
|
return skb;
|
||||||
dest = eth_hdr(skb)->h_dest;
|
dest = eth_hdr(skb)->h_dest;
|
||||||
}
|
}
|
||||||
|
@ -503,18 +503,14 @@ inhdr_error:
|
|||||||
* receiving device) to make netfilter happy, the REDIRECT
|
* receiving device) to make netfilter happy, the REDIRECT
|
||||||
* target in particular. Save the original destination IP
|
* target in particular. Save the original destination IP
|
||||||
* address to be able to detect DNAT afterwards. */
|
* address to be able to detect DNAT afterwards. */
|
||||||
static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
|
static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
struct sk_buff *skb = *pskb;
|
|
||||||
__u32 len = nf_bridge_encap_header_len(skb);
|
__u32 len = nf_bridge_encap_header_len(skb);
|
||||||
|
|
||||||
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
|
|
||||||
return NF_STOLEN;
|
|
||||||
|
|
||||||
if (unlikely(!pskb_may_pull(skb, len)))
|
if (unlikely(!pskb_may_pull(skb, len)))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -584,13 +580,11 @@ out:
|
|||||||
* took place when the packet entered the bridge), but we
|
* took place when the packet entered the bridge), but we
|
||||||
* register an IPv4 PRE_ROUTING 'sabotage' hook that will
|
* register an IPv4 PRE_ROUTING 'sabotage' hook that will
|
||||||
* prevent this from happening. */
|
* prevent this from happening. */
|
||||||
static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb,
|
static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
struct sk_buff *skb = *pskb;
|
|
||||||
|
|
||||||
if (skb->dst == (struct dst_entry *)&__fake_rtable) {
|
if (skb->dst == (struct dst_entry *)&__fake_rtable) {
|
||||||
dst_release(skb->dst);
|
dst_release(skb->dst);
|
||||||
skb->dst = NULL;
|
skb->dst = NULL;
|
||||||
@ -625,12 +619,11 @@ static int br_nf_forward_finish(struct sk_buff *skb)
|
|||||||
* but we are still able to filter on the 'real' indev/outdev
|
* but we are still able to filter on the 'real' indev/outdev
|
||||||
* because of the physdev module. For ARP, indev and outdev are the
|
* because of the physdev module. For ARP, indev and outdev are the
|
||||||
* bridge ports. */
|
* bridge ports. */
|
||||||
static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
|
static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
struct sk_buff *skb = *pskb;
|
|
||||||
struct nf_bridge_info *nf_bridge;
|
struct nf_bridge_info *nf_bridge;
|
||||||
struct net_device *parent;
|
struct net_device *parent;
|
||||||
int pf;
|
int pf;
|
||||||
@ -648,7 +641,7 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
|
|||||||
else
|
else
|
||||||
pf = PF_INET6;
|
pf = PF_INET6;
|
||||||
|
|
||||||
nf_bridge_pull_encap_header(*pskb);
|
nf_bridge_pull_encap_header(skb);
|
||||||
|
|
||||||
nf_bridge = skb->nf_bridge;
|
nf_bridge = skb->nf_bridge;
|
||||||
if (skb->pkt_type == PACKET_OTHERHOST) {
|
if (skb->pkt_type == PACKET_OTHERHOST) {
|
||||||
@ -666,12 +659,11 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
|
|||||||
return NF_STOLEN;
|
return NF_STOLEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
|
static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
struct sk_buff *skb = *pskb;
|
|
||||||
struct net_device **d = (struct net_device **)(skb->cb);
|
struct net_device **d = (struct net_device **)(skb->cb);
|
||||||
|
|
||||||
#ifdef CONFIG_SYSCTL
|
#ifdef CONFIG_SYSCTL
|
||||||
@ -682,12 +674,12 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
|
|||||||
if (skb->protocol != htons(ETH_P_ARP)) {
|
if (skb->protocol != htons(ETH_P_ARP)) {
|
||||||
if (!IS_VLAN_ARP(skb))
|
if (!IS_VLAN_ARP(skb))
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
nf_bridge_pull_encap_header(*pskb);
|
nf_bridge_pull_encap_header(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arp_hdr(skb)->ar_pln != 4) {
|
if (arp_hdr(skb)->ar_pln != 4) {
|
||||||
if (IS_VLAN_ARP(skb))
|
if (IS_VLAN_ARP(skb))
|
||||||
nf_bridge_push_encap_header(*pskb);
|
nf_bridge_push_encap_header(skb);
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
}
|
}
|
||||||
*d = (struct net_device *)in;
|
*d = (struct net_device *)in;
|
||||||
@ -709,13 +701,12 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
|
|||||||
* NF_BR_PRI_FIRST, so no relevant PF_BRIDGE/INPUT functions have been nor
|
* NF_BR_PRI_FIRST, so no relevant PF_BRIDGE/INPUT functions have been nor
|
||||||
* will be executed.
|
* will be executed.
|
||||||
*/
|
*/
|
||||||
static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
|
static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
struct net_device *realindev;
|
struct net_device *realindev;
|
||||||
struct sk_buff *skb = *pskb;
|
|
||||||
struct nf_bridge_info *nf_bridge;
|
struct nf_bridge_info *nf_bridge;
|
||||||
|
|
||||||
if (!skb->nf_bridge)
|
if (!skb->nf_bridge)
|
||||||
@ -752,13 +743,12 @@ static int br_nf_dev_queue_xmit(struct sk_buff *skb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* PF_BRIDGE/POST_ROUTING ********************************************/
|
/* PF_BRIDGE/POST_ROUTING ********************************************/
|
||||||
static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
|
static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
struct sk_buff *skb = *pskb;
|
struct nf_bridge_info *nf_bridge = skb->nf_bridge;
|
||||||
struct nf_bridge_info *nf_bridge = (*pskb)->nf_bridge;
|
|
||||||
struct net_device *realoutdev = bridge_parent(skb->dev);
|
struct net_device *realoutdev = bridge_parent(skb->dev);
|
||||||
int pf;
|
int pf;
|
||||||
|
|
||||||
@ -828,13 +818,13 @@ print_error:
|
|||||||
/* IP/SABOTAGE *****************************************************/
|
/* IP/SABOTAGE *****************************************************/
|
||||||
/* Don't hand locally destined packets to PF_INET(6)/PRE_ROUTING
|
/* Don't hand locally destined packets to PF_INET(6)/PRE_ROUTING
|
||||||
* for the second time. */
|
* for the second time. */
|
||||||
static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb,
|
static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
if ((*pskb)->nf_bridge &&
|
if (skb->nf_bridge &&
|
||||||
!((*pskb)->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) {
|
!(skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) {
|
||||||
return NF_STOP;
|
return NF_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#include <net/arp.h>
|
#include <net/arp.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
|
||||||
static int ebt_target_reply(struct sk_buff **pskb, unsigned int hooknr,
|
static int ebt_target_reply(struct sk_buff *skb, unsigned int hooknr,
|
||||||
const struct net_device *in, const struct net_device *out,
|
const struct net_device *in, const struct net_device *out,
|
||||||
const void *data, unsigned int datalen)
|
const void *data, unsigned int datalen)
|
||||||
{
|
{
|
||||||
@ -23,7 +23,6 @@ static int ebt_target_reply(struct sk_buff **pskb, unsigned int hooknr,
|
|||||||
__be32 _sip, *siptr, _dip, *diptr;
|
__be32 _sip, *siptr, _dip, *diptr;
|
||||||
struct arphdr _ah, *ap;
|
struct arphdr _ah, *ap;
|
||||||
unsigned char _sha[ETH_ALEN], *shp;
|
unsigned char _sha[ETH_ALEN], *shp;
|
||||||
struct sk_buff *skb = *pskb;
|
|
||||||
|
|
||||||
ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
|
ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
|
||||||
if (ap == NULL)
|
if (ap == NULL)
|
||||||
|
@ -8,29 +8,22 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/netfilter.h>
|
||||||
#include <linux/netfilter_bridge/ebtables.h>
|
#include <linux/netfilter_bridge/ebtables.h>
|
||||||
#include <linux/netfilter_bridge/ebt_nat.h>
|
#include <linux/netfilter_bridge/ebt_nat.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <net/sock.h>
|
#include <net/sock.h>
|
||||||
|
|
||||||
static int ebt_target_dnat(struct sk_buff **pskb, unsigned int hooknr,
|
static int ebt_target_dnat(struct sk_buff *skb, unsigned int hooknr,
|
||||||
const struct net_device *in, const struct net_device *out,
|
const struct net_device *in, const struct net_device *out,
|
||||||
const void *data, unsigned int datalen)
|
const void *data, unsigned int datalen)
|
||||||
{
|
{
|
||||||
struct ebt_nat_info *info = (struct ebt_nat_info *)data;
|
struct ebt_nat_info *info = (struct ebt_nat_info *)data;
|
||||||
|
|
||||||
if (skb_shared(*pskb) || skb_cloned(*pskb)) {
|
if (skb_make_writable(skb, 0))
|
||||||
struct sk_buff *nskb;
|
return NF_DROP;
|
||||||
|
|
||||||
nskb = skb_copy(*pskb, GFP_ATOMIC);
|
memcpy(eth_hdr(skb)->h_dest, info->mac, ETH_ALEN);
|
||||||
if (!nskb)
|
|
||||||
return NF_DROP;
|
|
||||||
if ((*pskb)->sk)
|
|
||||||
skb_set_owner_w(nskb, (*pskb)->sk);
|
|
||||||
kfree_skb(*pskb);
|
|
||||||
*pskb = nskb;
|
|
||||||
}
|
|
||||||
memcpy(eth_hdr(*pskb)->h_dest, info->mac, ETH_ALEN);
|
|
||||||
return info->target;
|
return info->target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
#include <linux/netfilter_bridge/ebt_mark_t.h>
|
#include <linux/netfilter_bridge/ebt_mark_t.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
|
||||||
static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr,
|
static int ebt_target_mark(struct sk_buff *skb, unsigned int hooknr,
|
||||||
const struct net_device *in, const struct net_device *out,
|
const struct net_device *in, const struct net_device *out,
|
||||||
const void *data, unsigned int datalen)
|
const void *data, unsigned int datalen)
|
||||||
{
|
{
|
||||||
@ -25,13 +25,13 @@ static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr,
|
|||||||
int action = info->target & -16;
|
int action = info->target & -16;
|
||||||
|
|
||||||
if (action == MARK_SET_VALUE)
|
if (action == MARK_SET_VALUE)
|
||||||
(*pskb)->mark = info->mark;
|
skb->mark = info->mark;
|
||||||
else if (action == MARK_OR_VALUE)
|
else if (action == MARK_OR_VALUE)
|
||||||
(*pskb)->mark |= info->mark;
|
skb->mark |= info->mark;
|
||||||
else if (action == MARK_AND_VALUE)
|
else if (action == MARK_AND_VALUE)
|
||||||
(*pskb)->mark &= info->mark;
|
skb->mark &= info->mark;
|
||||||
else
|
else
|
||||||
(*pskb)->mark ^= info->mark;
|
skb->mark ^= info->mark;
|
||||||
|
|
||||||
return info->target | ~EBT_VERDICT_BITS;
|
return info->target | ~EBT_VERDICT_BITS;
|
||||||
}
|
}
|
||||||
|
@ -8,35 +8,28 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/netfilter.h>
|
||||||
#include <linux/netfilter_bridge/ebtables.h>
|
#include <linux/netfilter_bridge/ebtables.h>
|
||||||
#include <linux/netfilter_bridge/ebt_redirect.h>
|
#include <linux/netfilter_bridge/ebt_redirect.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <net/sock.h>
|
#include <net/sock.h>
|
||||||
#include "../br_private.h"
|
#include "../br_private.h"
|
||||||
|
|
||||||
static int ebt_target_redirect(struct sk_buff **pskb, unsigned int hooknr,
|
static int ebt_target_redirect(struct sk_buff *skb, unsigned int hooknr,
|
||||||
const struct net_device *in, const struct net_device *out,
|
const struct net_device *in, const struct net_device *out,
|
||||||
const void *data, unsigned int datalen)
|
const void *data, unsigned int datalen)
|
||||||
{
|
{
|
||||||
struct ebt_redirect_info *info = (struct ebt_redirect_info *)data;
|
struct ebt_redirect_info *info = (struct ebt_redirect_info *)data;
|
||||||
|
|
||||||
if (skb_shared(*pskb) || skb_cloned(*pskb)) {
|
if (skb_make_writable(skb, 0))
|
||||||
struct sk_buff *nskb;
|
return NF_DROP;
|
||||||
|
|
||||||
nskb = skb_copy(*pskb, GFP_ATOMIC);
|
|
||||||
if (!nskb)
|
|
||||||
return NF_DROP;
|
|
||||||
if ((*pskb)->sk)
|
|
||||||
skb_set_owner_w(nskb, (*pskb)->sk);
|
|
||||||
kfree_skb(*pskb);
|
|
||||||
*pskb = nskb;
|
|
||||||
}
|
|
||||||
if (hooknr != NF_BR_BROUTING)
|
if (hooknr != NF_BR_BROUTING)
|
||||||
memcpy(eth_hdr(*pskb)->h_dest,
|
memcpy(eth_hdr(skb)->h_dest,
|
||||||
in->br_port->br->dev->dev_addr, ETH_ALEN);
|
in->br_port->br->dev->dev_addr, ETH_ALEN);
|
||||||
else
|
else
|
||||||
memcpy(eth_hdr(*pskb)->h_dest, in->dev_addr, ETH_ALEN);
|
memcpy(eth_hdr(skb)->h_dest, in->dev_addr, ETH_ALEN);
|
||||||
(*pskb)->pkt_type = PACKET_HOST;
|
skb->pkt_type = PACKET_HOST;
|
||||||
return info->target;
|
return info->target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/netfilter.h>
|
||||||
#include <linux/netfilter_bridge/ebtables.h>
|
#include <linux/netfilter_bridge/ebtables.h>
|
||||||
#include <linux/netfilter_bridge/ebt_nat.h>
|
#include <linux/netfilter_bridge/ebt_nat.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
@ -15,34 +16,26 @@
|
|||||||
#include <linux/if_arp.h>
|
#include <linux/if_arp.h>
|
||||||
#include <net/arp.h>
|
#include <net/arp.h>
|
||||||
|
|
||||||
static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr,
|
static int ebt_target_snat(struct sk_buff *skb, unsigned int hooknr,
|
||||||
const struct net_device *in, const struct net_device *out,
|
const struct net_device *in, const struct net_device *out,
|
||||||
const void *data, unsigned int datalen)
|
const void *data, unsigned int datalen)
|
||||||
{
|
{
|
||||||
struct ebt_nat_info *info = (struct ebt_nat_info *) data;
|
struct ebt_nat_info *info = (struct ebt_nat_info *) data;
|
||||||
|
|
||||||
if (skb_shared(*pskb) || skb_cloned(*pskb)) {
|
if (skb_make_writable(skb, 0))
|
||||||
struct sk_buff *nskb;
|
return NF_DROP;
|
||||||
|
|
||||||
nskb = skb_copy(*pskb, GFP_ATOMIC);
|
memcpy(eth_hdr(skb)->h_source, info->mac, ETH_ALEN);
|
||||||
if (!nskb)
|
|
||||||
return NF_DROP;
|
|
||||||
if ((*pskb)->sk)
|
|
||||||
skb_set_owner_w(nskb, (*pskb)->sk);
|
|
||||||
kfree_skb(*pskb);
|
|
||||||
*pskb = nskb;
|
|
||||||
}
|
|
||||||
memcpy(eth_hdr(*pskb)->h_source, info->mac, ETH_ALEN);
|
|
||||||
if (!(info->target & NAT_ARP_BIT) &&
|
if (!(info->target & NAT_ARP_BIT) &&
|
||||||
eth_hdr(*pskb)->h_proto == htons(ETH_P_ARP)) {
|
eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
|
||||||
struct arphdr _ah, *ap;
|
struct arphdr _ah, *ap;
|
||||||
|
|
||||||
ap = skb_header_pointer(*pskb, 0, sizeof(_ah), &_ah);
|
ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
|
||||||
if (ap == NULL)
|
if (ap == NULL)
|
||||||
return EBT_DROP;
|
return EBT_DROP;
|
||||||
if (ap->ar_hln != ETH_ALEN)
|
if (ap->ar_hln != ETH_ALEN)
|
||||||
goto out;
|
goto out;
|
||||||
if (skb_store_bits(*pskb, sizeof(_ah), info->mac,ETH_ALEN))
|
if (skb_store_bits(skb, sizeof(_ah), info->mac,ETH_ALEN))
|
||||||
return EBT_DROP;
|
return EBT_DROP;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
@ -51,11 +51,11 @@ static struct ebt_table broute_table =
|
|||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ebt_broute(struct sk_buff **pskb)
|
static int ebt_broute(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = ebt_do_table(NF_BR_BROUTING, pskb, (*pskb)->dev, NULL,
|
ret = ebt_do_table(NF_BR_BROUTING, skb, skb->dev, NULL,
|
||||||
&broute_table);
|
&broute_table);
|
||||||
if (ret == NF_DROP)
|
if (ret == NF_DROP)
|
||||||
return 1; /* route it */
|
return 1; /* route it */
|
||||||
|
@ -61,10 +61,10 @@ static struct ebt_table frame_filter =
|
|||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
ebt_hook (unsigned int hook, struct sk_buff **pskb, const struct net_device *in,
|
ebt_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in,
|
||||||
const struct net_device *out, int (*okfn)(struct sk_buff *))
|
const struct net_device *out, int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
return ebt_do_table(hook, pskb, in, out, &frame_filter);
|
return ebt_do_table(hook, skb, in, out, &frame_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct nf_hook_ops ebt_ops_filter[] = {
|
static struct nf_hook_ops ebt_ops_filter[] = {
|
||||||
|
@ -61,17 +61,17 @@ static struct ebt_table frame_nat =
|
|||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
ebt_nat_dst(unsigned int hook, struct sk_buff **pskb, const struct net_device *in
|
ebt_nat_dst(unsigned int hook, struct sk_buff *skb, const struct net_device *in
|
||||||
, const struct net_device *out, int (*okfn)(struct sk_buff *))
|
, const struct net_device *out, int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
return ebt_do_table(hook, pskb, in, out, &frame_nat);
|
return ebt_do_table(hook, skb, in, out, &frame_nat);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
ebt_nat_src(unsigned int hook, struct sk_buff **pskb, const struct net_device *in
|
ebt_nat_src(unsigned int hook, struct sk_buff *skb, const struct net_device *in
|
||||||
, const struct net_device *out, int (*okfn)(struct sk_buff *))
|
, const struct net_device *out, int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
return ebt_do_table(hook, pskb, in, out, &frame_nat);
|
return ebt_do_table(hook, skb, in, out, &frame_nat);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct nf_hook_ops ebt_ops_nat[] = {
|
static struct nf_hook_ops ebt_ops_nat[] = {
|
||||||
|
@ -142,7 +142,7 @@ static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Do some firewalling */
|
/* Do some firewalling */
|
||||||
unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
|
unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
|
||||||
const struct net_device *in, const struct net_device *out,
|
const struct net_device *in, const struct net_device *out,
|
||||||
struct ebt_table *table)
|
struct ebt_table *table)
|
||||||
{
|
{
|
||||||
@ -172,19 +172,19 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
|
|||||||
base = private->entries;
|
base = private->entries;
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < nentries) {
|
while (i < nentries) {
|
||||||
if (ebt_basic_match(point, eth_hdr(*pskb), in, out))
|
if (ebt_basic_match(point, eth_hdr(skb), in, out))
|
||||||
goto letscontinue;
|
goto letscontinue;
|
||||||
|
|
||||||
if (EBT_MATCH_ITERATE(point, ebt_do_match, *pskb, in, out) != 0)
|
if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, in, out) != 0)
|
||||||
goto letscontinue;
|
goto letscontinue;
|
||||||
|
|
||||||
/* increase counter */
|
/* increase counter */
|
||||||
(*(counter_base + i)).pcnt++;
|
(*(counter_base + i)).pcnt++;
|
||||||
(*(counter_base + i)).bcnt+=(**pskb).len;
|
(*(counter_base + i)).bcnt += skb->len;
|
||||||
|
|
||||||
/* these should only watch: not modify, nor tell us
|
/* these should only watch: not modify, nor tell us
|
||||||
what to do with the packet */
|
what to do with the packet */
|
||||||
EBT_WATCHER_ITERATE(point, ebt_do_watcher, *pskb, hook, in,
|
EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, hook, in,
|
||||||
out);
|
out);
|
||||||
|
|
||||||
t = (struct ebt_entry_target *)
|
t = (struct ebt_entry_target *)
|
||||||
@ -193,7 +193,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
|
|||||||
if (!t->u.target->target)
|
if (!t->u.target->target)
|
||||||
verdict = ((struct ebt_standard_target *)t)->verdict;
|
verdict = ((struct ebt_standard_target *)t)->verdict;
|
||||||
else
|
else
|
||||||
verdict = t->u.target->target(pskb, hook,
|
verdict = t->u.target->target(skb, hook,
|
||||||
in, out, t->data, t->target_size);
|
in, out, t->data, t->target_size);
|
||||||
if (verdict == EBT_ACCEPT) {
|
if (verdict == EBT_ACCEPT) {
|
||||||
read_unlock_bh(&table->lock);
|
read_unlock_bh(&table->lock);
|
||||||
|
@ -1362,22 +1362,21 @@ int skb_checksum_help(struct sk_buff *skb)
|
|||||||
goto out_set_summed;
|
goto out_set_summed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skb_cloned(skb)) {
|
offset = skb->csum_start - skb_headroom(skb);
|
||||||
|
BUG_ON(offset >= skb_headlen(skb));
|
||||||
|
csum = skb_checksum(skb, offset, skb->len - offset, 0);
|
||||||
|
|
||||||
|
offset += skb->csum_offset;
|
||||||
|
BUG_ON(offset + sizeof(__sum16) > skb_headlen(skb));
|
||||||
|
|
||||||
|
if (skb_cloned(skb) &&
|
||||||
|
!skb_clone_writable(skb, offset + sizeof(__sum16))) {
|
||||||
ret = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
|
ret = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = skb->csum_start - skb_headroom(skb);
|
*(__sum16 *)(skb->data + offset) = csum_fold(csum);
|
||||||
BUG_ON(offset > (int)skb->len);
|
|
||||||
csum = skb_checksum(skb, offset, skb->len-offset, 0);
|
|
||||||
|
|
||||||
offset = skb_headlen(skb) - offset;
|
|
||||||
BUG_ON(offset <= 0);
|
|
||||||
BUG_ON(skb->csum_offset + 2 > offset);
|
|
||||||
|
|
||||||
*(__sum16 *)(skb->head + skb->csum_start + skb->csum_offset) =
|
|
||||||
csum_fold(csum);
|
|
||||||
out_set_summed:
|
out_set_summed:
|
||||||
skb->ip_summed = CHECKSUM_NONE;
|
skb->ip_summed = CHECKSUM_NONE;
|
||||||
out:
|
out:
|
||||||
@ -1949,28 +1948,52 @@ static int ing_filter(struct sk_buff *skb)
|
|||||||
struct Qdisc *q;
|
struct Qdisc *q;
|
||||||
struct net_device *dev = skb->dev;
|
struct net_device *dev = skb->dev;
|
||||||
int result = TC_ACT_OK;
|
int result = TC_ACT_OK;
|
||||||
|
u32 ttl = G_TC_RTTL(skb->tc_verd);
|
||||||
|
|
||||||
if (dev->qdisc_ingress) {
|
if (MAX_RED_LOOP < ttl++) {
|
||||||
__u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd);
|
printk(KERN_WARNING
|
||||||
if (MAX_RED_LOOP < ttl++) {
|
"Redir loop detected Dropping packet (%d->%d)\n",
|
||||||
printk(KERN_WARNING "Redir loop detected Dropping packet (%d->%d)\n",
|
skb->iif, dev->ifindex);
|
||||||
skb->iif, skb->dev->ifindex);
|
return TC_ACT_SHOT;
|
||||||
return TC_ACT_SHOT;
|
|
||||||
}
|
|
||||||
|
|
||||||
skb->tc_verd = SET_TC_RTTL(skb->tc_verd,ttl);
|
|
||||||
|
|
||||||
skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS);
|
|
||||||
|
|
||||||
spin_lock(&dev->ingress_lock);
|
|
||||||
if ((q = dev->qdisc_ingress) != NULL)
|
|
||||||
result = q->enqueue(skb, q);
|
|
||||||
spin_unlock(&dev->ingress_lock);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skb->tc_verd = SET_TC_RTTL(skb->tc_verd, ttl);
|
||||||
|
skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_INGRESS);
|
||||||
|
|
||||||
|
spin_lock(&dev->ingress_lock);
|
||||||
|
if ((q = dev->qdisc_ingress) != NULL)
|
||||||
|
result = q->enqueue(skb, q);
|
||||||
|
spin_unlock(&dev->ingress_lock);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct sk_buff *handle_ing(struct sk_buff *skb,
|
||||||
|
struct packet_type **pt_prev,
|
||||||
|
int *ret, struct net_device *orig_dev)
|
||||||
|
{
|
||||||
|
if (!skb->dev->qdisc_ingress)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (*pt_prev) {
|
||||||
|
*ret = deliver_skb(skb, *pt_prev, orig_dev);
|
||||||
|
*pt_prev = NULL;
|
||||||
|
} else {
|
||||||
|
/* Huh? Why does turning on AF_PACKET affect this? */
|
||||||
|
skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ing_filter(skb)) {
|
||||||
|
case TC_ACT_SHOT:
|
||||||
|
case TC_ACT_STOLEN:
|
||||||
|
kfree_skb(skb);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
skb->tc_verd = 0;
|
||||||
|
return skb;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int netif_receive_skb(struct sk_buff *skb)
|
int netif_receive_skb(struct sk_buff *skb)
|
||||||
@ -2021,21 +2044,9 @@ int netif_receive_skb(struct sk_buff *skb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_NET_CLS_ACT
|
#ifdef CONFIG_NET_CLS_ACT
|
||||||
if (pt_prev) {
|
skb = handle_ing(skb, &pt_prev, &ret, orig_dev);
|
||||||
ret = deliver_skb(skb, pt_prev, orig_dev);
|
if (!skb)
|
||||||
pt_prev = NULL; /* noone else should process this after*/
|
|
||||||
} else {
|
|
||||||
skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = ing_filter(skb);
|
|
||||||
|
|
||||||
if (ret == TC_ACT_SHOT || (ret == TC_ACT_STOLEN)) {
|
|
||||||
kfree_skb(skb);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
skb->tc_verd = 0;
|
|
||||||
ncls:
|
ncls:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -481,6 +481,8 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, const void *pkey,
|
|||||||
if (!creat)
|
if (!creat)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
ASSERT_RTNL();
|
||||||
|
|
||||||
n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
|
n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
|
||||||
if (!n)
|
if (!n)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -362,6 +362,97 @@ void kfree_skb(struct sk_buff *skb)
|
|||||||
__kfree_skb(skb);
|
__kfree_skb(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
|
||||||
|
{
|
||||||
|
new->tstamp = old->tstamp;
|
||||||
|
new->dev = old->dev;
|
||||||
|
new->transport_header = old->transport_header;
|
||||||
|
new->network_header = old->network_header;
|
||||||
|
new->mac_header = old->mac_header;
|
||||||
|
new->dst = dst_clone(old->dst);
|
||||||
|
#ifdef CONFIG_INET
|
||||||
|
new->sp = secpath_get(old->sp);
|
||||||
|
#endif
|
||||||
|
memcpy(new->cb, old->cb, sizeof(old->cb));
|
||||||
|
new->csum_start = old->csum_start;
|
||||||
|
new->csum_offset = old->csum_offset;
|
||||||
|
new->local_df = old->local_df;
|
||||||
|
new->pkt_type = old->pkt_type;
|
||||||
|
new->ip_summed = old->ip_summed;
|
||||||
|
skb_copy_queue_mapping(new, old);
|
||||||
|
new->priority = old->priority;
|
||||||
|
#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
|
||||||
|
new->ipvs_property = old->ipvs_property;
|
||||||
|
#endif
|
||||||
|
new->protocol = old->protocol;
|
||||||
|
new->mark = old->mark;
|
||||||
|
__nf_copy(new, old);
|
||||||
|
#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
|
||||||
|
defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
|
||||||
|
new->nf_trace = old->nf_trace;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_NET_SCHED
|
||||||
|
new->tc_index = old->tc_index;
|
||||||
|
#ifdef CONFIG_NET_CLS_ACT
|
||||||
|
new->tc_verd = old->tc_verd;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
skb_copy_secmark(new, old);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
#define C(x) n->x = skb->x
|
||||||
|
|
||||||
|
n->next = n->prev = NULL;
|
||||||
|
n->sk = NULL;
|
||||||
|
__copy_skb_header(n, skb);
|
||||||
|
|
||||||
|
C(len);
|
||||||
|
C(data_len);
|
||||||
|
C(mac_len);
|
||||||
|
n->cloned = 1;
|
||||||
|
n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
|
||||||
|
n->nohdr = 0;
|
||||||
|
n->destructor = NULL;
|
||||||
|
#ifdef CONFIG_NET_CLS_ACT
|
||||||
|
/* FIXME What is this and why don't we do it in copy_skb_header? */
|
||||||
|
n->tc_verd = SET_TC_VERD(n->tc_verd,0);
|
||||||
|
n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd);
|
||||||
|
n->tc_verd = CLR_TC_MUNGED(n->tc_verd);
|
||||||
|
C(iif);
|
||||||
|
#endif
|
||||||
|
C(truesize);
|
||||||
|
atomic_set(&n->users, 1);
|
||||||
|
C(head);
|
||||||
|
C(data);
|
||||||
|
C(tail);
|
||||||
|
C(end);
|
||||||
|
|
||||||
|
atomic_inc(&(skb_shinfo(skb)->dataref));
|
||||||
|
skb->cloned = 1;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
#undef C
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* skb_morph - morph one skb into another
|
||||||
|
* @dst: the skb to receive the contents
|
||||||
|
* @src: the skb to supply the contents
|
||||||
|
*
|
||||||
|
* This is identical to skb_clone except that the target skb is
|
||||||
|
* supplied by the user.
|
||||||
|
*
|
||||||
|
* The target skb is returned upon exit.
|
||||||
|
*/
|
||||||
|
struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src)
|
||||||
|
{
|
||||||
|
skb_release_data(dst);
|
||||||
|
return __skb_clone(dst, src);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(skb_morph);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* skb_clone - duplicate an sk_buff
|
* skb_clone - duplicate an sk_buff
|
||||||
* @skb: buffer to clone
|
* @skb: buffer to clone
|
||||||
@ -393,66 +484,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
|
|||||||
n->fclone = SKB_FCLONE_UNAVAILABLE;
|
n->fclone = SKB_FCLONE_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define C(x) n->x = skb->x
|
return __skb_clone(n, skb);
|
||||||
|
|
||||||
n->next = n->prev = NULL;
|
|
||||||
n->sk = NULL;
|
|
||||||
C(tstamp);
|
|
||||||
C(dev);
|
|
||||||
C(transport_header);
|
|
||||||
C(network_header);
|
|
||||||
C(mac_header);
|
|
||||||
C(dst);
|
|
||||||
dst_clone(skb->dst);
|
|
||||||
C(sp);
|
|
||||||
#ifdef CONFIG_INET
|
|
||||||
secpath_get(skb->sp);
|
|
||||||
#endif
|
|
||||||
memcpy(n->cb, skb->cb, sizeof(skb->cb));
|
|
||||||
C(len);
|
|
||||||
C(data_len);
|
|
||||||
C(mac_len);
|
|
||||||
C(csum);
|
|
||||||
C(local_df);
|
|
||||||
n->cloned = 1;
|
|
||||||
n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
|
|
||||||
n->nohdr = 0;
|
|
||||||
C(pkt_type);
|
|
||||||
C(ip_summed);
|
|
||||||
skb_copy_queue_mapping(n, skb);
|
|
||||||
C(priority);
|
|
||||||
#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
|
|
||||||
C(ipvs_property);
|
|
||||||
#endif
|
|
||||||
C(protocol);
|
|
||||||
n->destructor = NULL;
|
|
||||||
C(mark);
|
|
||||||
__nf_copy(n, skb);
|
|
||||||
#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
|
|
||||||
defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
|
|
||||||
C(nf_trace);
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_NET_SCHED
|
|
||||||
C(tc_index);
|
|
||||||
#ifdef CONFIG_NET_CLS_ACT
|
|
||||||
n->tc_verd = SET_TC_VERD(skb->tc_verd,0);
|
|
||||||
n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd);
|
|
||||||
n->tc_verd = CLR_TC_MUNGED(n->tc_verd);
|
|
||||||
C(iif);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
skb_copy_secmark(n, skb);
|
|
||||||
C(truesize);
|
|
||||||
atomic_set(&n->users, 1);
|
|
||||||
C(head);
|
|
||||||
C(data);
|
|
||||||
C(tail);
|
|
||||||
C(end);
|
|
||||||
|
|
||||||
atomic_inc(&(skb_shinfo(skb)->dataref));
|
|
||||||
skb->cloned = 1;
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
|
static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
|
||||||
@ -463,50 +495,15 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
|
|||||||
*/
|
*/
|
||||||
unsigned long offset = new->data - old->data;
|
unsigned long offset = new->data - old->data;
|
||||||
#endif
|
#endif
|
||||||
new->sk = NULL;
|
|
||||||
new->dev = old->dev;
|
__copy_skb_header(new, old);
|
||||||
skb_copy_queue_mapping(new, old);
|
|
||||||
new->priority = old->priority;
|
|
||||||
new->protocol = old->protocol;
|
|
||||||
new->dst = dst_clone(old->dst);
|
|
||||||
#ifdef CONFIG_INET
|
|
||||||
new->sp = secpath_get(old->sp);
|
|
||||||
#endif
|
|
||||||
new->csum_start = old->csum_start;
|
|
||||||
new->csum_offset = old->csum_offset;
|
|
||||||
new->ip_summed = old->ip_summed;
|
|
||||||
new->transport_header = old->transport_header;
|
|
||||||
new->network_header = old->network_header;
|
|
||||||
new->mac_header = old->mac_header;
|
|
||||||
#ifndef NET_SKBUFF_DATA_USES_OFFSET
|
#ifndef NET_SKBUFF_DATA_USES_OFFSET
|
||||||
/* {transport,network,mac}_header are relative to skb->head */
|
/* {transport,network,mac}_header are relative to skb->head */
|
||||||
new->transport_header += offset;
|
new->transport_header += offset;
|
||||||
new->network_header += offset;
|
new->network_header += offset;
|
||||||
new->mac_header += offset;
|
new->mac_header += offset;
|
||||||
#endif
|
#endif
|
||||||
memcpy(new->cb, old->cb, sizeof(old->cb));
|
|
||||||
new->local_df = old->local_df;
|
|
||||||
new->fclone = SKB_FCLONE_UNAVAILABLE;
|
|
||||||
new->pkt_type = old->pkt_type;
|
|
||||||
new->tstamp = old->tstamp;
|
|
||||||
new->destructor = NULL;
|
|
||||||
new->mark = old->mark;
|
|
||||||
__nf_copy(new, old);
|
|
||||||
#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
|
|
||||||
defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
|
|
||||||
new->nf_trace = old->nf_trace;
|
|
||||||
#endif
|
|
||||||
#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
|
|
||||||
new->ipvs_property = old->ipvs_property;
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_NET_SCHED
|
|
||||||
#ifdef CONFIG_NET_CLS_ACT
|
|
||||||
new->tc_verd = old->tc_verd;
|
|
||||||
#endif
|
|
||||||
new->tc_index = old->tc_index;
|
|
||||||
#endif
|
|
||||||
skb_copy_secmark(new, old);
|
|
||||||
atomic_set(&new->users, 1);
|
|
||||||
skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size;
|
skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size;
|
||||||
skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs;
|
skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs;
|
||||||
skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type;
|
skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type;
|
||||||
@ -685,7 +682,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
|
|||||||
skb->transport_header += off;
|
skb->transport_header += off;
|
||||||
skb->network_header += off;
|
skb->network_header += off;
|
||||||
skb->mac_header += off;
|
skb->mac_header += off;
|
||||||
skb->csum_start += off;
|
skb->csum_start += nhead;
|
||||||
skb->cloned = 0;
|
skb->cloned = 0;
|
||||||
skb->hdr_len = 0;
|
skb->hdr_len = 0;
|
||||||
skb->nohdr = 0;
|
skb->nohdr = 0;
|
||||||
|
@ -767,10 +767,9 @@ discard:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dccp_v6_rcv(struct sk_buff **pskb)
|
static int dccp_v6_rcv(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
const struct dccp_hdr *dh;
|
const struct dccp_hdr *dh;
|
||||||
struct sk_buff *skb = *pskb;
|
|
||||||
struct sock *sk;
|
struct sock *sk;
|
||||||
int min_cov;
|
int min_cov;
|
||||||
|
|
||||||
|
@ -88,12 +88,12 @@ static void dnrmg_send_peer(struct sk_buff *skb)
|
|||||||
|
|
||||||
|
|
||||||
static unsigned int dnrmg_hook(unsigned int hook,
|
static unsigned int dnrmg_hook(unsigned int hook,
|
||||||
struct sk_buff **pskb,
|
struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
dnrmg_send_peer(*pskb);
|
dnrmg_send_peer(skb);
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,8 @@ obj-y := route.o inetpeer.o protocol.o \
|
|||||||
tcp_minisocks.o tcp_cong.o \
|
tcp_minisocks.o tcp_cong.o \
|
||||||
datagram.o raw.o udp.o udplite.o \
|
datagram.o raw.o udp.o udplite.o \
|
||||||
arp.o icmp.o devinet.o af_inet.o igmp.o \
|
arp.o icmp.o devinet.o af_inet.o igmp.o \
|
||||||
sysctl_net_ipv4.o fib_frontend.o fib_semantics.o
|
sysctl_net_ipv4.o fib_frontend.o fib_semantics.o \
|
||||||
|
inet_fragment.o
|
||||||
|
|
||||||
obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o
|
obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o
|
||||||
obj-$(CONFIG_IP_FIB_TRIE) += fib_trie.o
|
obj-$(CONFIG_IP_FIB_TRIE) += fib_trie.o
|
||||||
|
174
net/ipv4/inet_fragment.c
Normal file
174
net/ipv4/inet_fragment.c
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
/*
|
||||||
|
* inet fragments management
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version
|
||||||
|
* 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Authors: Pavel Emelyanov <xemul@openvz.org>
|
||||||
|
* Started as consolidation of ipv4/ip_fragment.c,
|
||||||
|
* ipv6/reassembly. and ipv6 nf conntrack reassembly
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/timer.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/random.h>
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
#include <net/inet_frag.h>
|
||||||
|
|
||||||
|
static void inet_frag_secret_rebuild(unsigned long dummy)
|
||||||
|
{
|
||||||
|
struct inet_frags *f = (struct inet_frags *)dummy;
|
||||||
|
unsigned long now = jiffies;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
write_lock(&f->lock);
|
||||||
|
get_random_bytes(&f->rnd, sizeof(u32));
|
||||||
|
for (i = 0; i < INETFRAGS_HASHSZ; i++) {
|
||||||
|
struct inet_frag_queue *q;
|
||||||
|
struct hlist_node *p, *n;
|
||||||
|
|
||||||
|
hlist_for_each_entry_safe(q, p, n, &f->hash[i], list) {
|
||||||
|
unsigned int hval = f->hashfn(q);
|
||||||
|
|
||||||
|
if (hval != i) {
|
||||||
|
hlist_del(&q->list);
|
||||||
|
|
||||||
|
/* Relink to new hash chain. */
|
||||||
|
hlist_add_head(&q->list, &f->hash[hval]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write_unlock(&f->lock);
|
||||||
|
|
||||||
|
mod_timer(&f->secret_timer, now + f->ctl->secret_interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
void inet_frags_init(struct inet_frags *f)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < INETFRAGS_HASHSZ; i++)
|
||||||
|
INIT_HLIST_HEAD(&f->hash[i]);
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&f->lru_list);
|
||||||
|
rwlock_init(&f->lock);
|
||||||
|
|
||||||
|
f->rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
|
||||||
|
(jiffies ^ (jiffies >> 6)));
|
||||||
|
|
||||||
|
f->nqueues = 0;
|
||||||
|
atomic_set(&f->mem, 0);
|
||||||
|
|
||||||
|
init_timer(&f->secret_timer);
|
||||||
|
f->secret_timer.function = inet_frag_secret_rebuild;
|
||||||
|
f->secret_timer.data = (unsigned long)f;
|
||||||
|
f->secret_timer.expires = jiffies + f->ctl->secret_interval;
|
||||||
|
add_timer(&f->secret_timer);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(inet_frags_init);
|
||||||
|
|
||||||
|
void inet_frags_fini(struct inet_frags *f)
|
||||||
|
{
|
||||||
|
del_timer(&f->secret_timer);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(inet_frags_fini);
|
||||||
|
|
||||||
|
static inline void fq_unlink(struct inet_frag_queue *fq, struct inet_frags *f)
|
||||||
|
{
|
||||||
|
write_lock(&f->lock);
|
||||||
|
hlist_del(&fq->list);
|
||||||
|
list_del(&fq->lru_list);
|
||||||
|
f->nqueues--;
|
||||||
|
write_unlock(&f->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void inet_frag_kill(struct inet_frag_queue *fq, struct inet_frags *f)
|
||||||
|
{
|
||||||
|
if (del_timer(&fq->timer))
|
||||||
|
atomic_dec(&fq->refcnt);
|
||||||
|
|
||||||
|
if (!(fq->last_in & COMPLETE)) {
|
||||||
|
fq_unlink(fq, f);
|
||||||
|
atomic_dec(&fq->refcnt);
|
||||||
|
fq->last_in |= COMPLETE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(inet_frag_kill);
|
||||||
|
|
||||||
|
static inline void frag_kfree_skb(struct inet_frags *f, struct sk_buff *skb,
|
||||||
|
int *work)
|
||||||
|
{
|
||||||
|
if (work)
|
||||||
|
*work -= skb->truesize;
|
||||||
|
|
||||||
|
atomic_sub(skb->truesize, &f->mem);
|
||||||
|
if (f->skb_free)
|
||||||
|
f->skb_free(skb);
|
||||||
|
kfree_skb(skb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f,
|
||||||
|
int *work)
|
||||||
|
{
|
||||||
|
struct sk_buff *fp;
|
||||||
|
|
||||||
|
BUG_TRAP(q->last_in & COMPLETE);
|
||||||
|
BUG_TRAP(del_timer(&q->timer) == 0);
|
||||||
|
|
||||||
|
/* Release all fragment data. */
|
||||||
|
fp = q->fragments;
|
||||||
|
while (fp) {
|
||||||
|
struct sk_buff *xp = fp->next;
|
||||||
|
|
||||||
|
frag_kfree_skb(f, fp, work);
|
||||||
|
fp = xp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (work)
|
||||||
|
*work -= f->qsize;
|
||||||
|
atomic_sub(f->qsize, &f->mem);
|
||||||
|
|
||||||
|
f->destructor(q);
|
||||||
|
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(inet_frag_destroy);
|
||||||
|
|
||||||
|
int inet_frag_evictor(struct inet_frags *f)
|
||||||
|
{
|
||||||
|
struct inet_frag_queue *q;
|
||||||
|
int work, evicted = 0;
|
||||||
|
|
||||||
|
work = atomic_read(&f->mem) - f->ctl->low_thresh;
|
||||||
|
while (work > 0) {
|
||||||
|
read_lock(&f->lock);
|
||||||
|
if (list_empty(&f->lru_list)) {
|
||||||
|
read_unlock(&f->lock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
q = list_first_entry(&f->lru_list,
|
||||||
|
struct inet_frag_queue, lru_list);
|
||||||
|
atomic_inc(&q->refcnt);
|
||||||
|
read_unlock(&f->lock);
|
||||||
|
|
||||||
|
spin_lock(&q->lock);
|
||||||
|
if (!(q->last_in & COMPLETE))
|
||||||
|
inet_frag_kill(q, f);
|
||||||
|
spin_unlock(&q->lock);
|
||||||
|
|
||||||
|
if (atomic_dec_and_test(&q->refcnt))
|
||||||
|
inet_frag_destroy(q, f, &work);
|
||||||
|
evicted++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return evicted;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(inet_frag_evictor);
|
@ -40,7 +40,7 @@
|
|||||||
#include <net/route.h>
|
#include <net/route.h>
|
||||||
#include <net/xfrm.h>
|
#include <net/xfrm.h>
|
||||||
|
|
||||||
static inline int ip_forward_finish(struct sk_buff *skb)
|
static int ip_forward_finish(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct ip_options * opt = &(IPCB(skb)->opt);
|
struct ip_options * opt = &(IPCB(skb)->opt);
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include <net/icmp.h>
|
#include <net/icmp.h>
|
||||||
#include <net/checksum.h>
|
#include <net/checksum.h>
|
||||||
#include <net/inetpeer.h>
|
#include <net/inetpeer.h>
|
||||||
|
#include <net/inet_frag.h>
|
||||||
#include <linux/tcp.h>
|
#include <linux/tcp.h>
|
||||||
#include <linux/udp.h>
|
#include <linux/udp.h>
|
||||||
#include <linux/inet.h>
|
#include <linux/inet.h>
|
||||||
@ -49,21 +50,8 @@
|
|||||||
* as well. Or notify me, at least. --ANK
|
* as well. Or notify me, at least. --ANK
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Fragment cache limits. We will commit 256K at one time. Should we
|
|
||||||
* cross that limit we will prune down to 192K. This should cope with
|
|
||||||
* even the most extreme cases without allowing an attacker to measurably
|
|
||||||
* harm machine performance.
|
|
||||||
*/
|
|
||||||
int sysctl_ipfrag_high_thresh __read_mostly = 256*1024;
|
|
||||||
int sysctl_ipfrag_low_thresh __read_mostly = 192*1024;
|
|
||||||
|
|
||||||
int sysctl_ipfrag_max_dist __read_mostly = 64;
|
int sysctl_ipfrag_max_dist __read_mostly = 64;
|
||||||
|
|
||||||
/* Important NOTE! Fragment queue must be destroyed before MSL expires.
|
|
||||||
* RFC791 is wrong proposing to prolongate timer each fragment arrival by TTL.
|
|
||||||
*/
|
|
||||||
int sysctl_ipfrag_time __read_mostly = IP_FRAG_TIME;
|
|
||||||
|
|
||||||
struct ipfrag_skb_cb
|
struct ipfrag_skb_cb
|
||||||
{
|
{
|
||||||
struct inet_skb_parm h;
|
struct inet_skb_parm h;
|
||||||
@ -74,153 +62,102 @@ struct ipfrag_skb_cb
|
|||||||
|
|
||||||
/* Describe an entry in the "incomplete datagrams" queue. */
|
/* Describe an entry in the "incomplete datagrams" queue. */
|
||||||
struct ipq {
|
struct ipq {
|
||||||
struct hlist_node list;
|
struct inet_frag_queue q;
|
||||||
struct list_head lru_list; /* lru list member */
|
|
||||||
u32 user;
|
u32 user;
|
||||||
__be32 saddr;
|
__be32 saddr;
|
||||||
__be32 daddr;
|
__be32 daddr;
|
||||||
__be16 id;
|
__be16 id;
|
||||||
u8 protocol;
|
u8 protocol;
|
||||||
u8 last_in;
|
|
||||||
#define COMPLETE 4
|
|
||||||
#define FIRST_IN 2
|
|
||||||
#define LAST_IN 1
|
|
||||||
|
|
||||||
struct sk_buff *fragments; /* linked list of received fragments */
|
|
||||||
int len; /* total length of original datagram */
|
|
||||||
int meat;
|
|
||||||
spinlock_t lock;
|
|
||||||
atomic_t refcnt;
|
|
||||||
struct timer_list timer; /* when will this queue expire? */
|
|
||||||
ktime_t stamp;
|
|
||||||
int iif;
|
int iif;
|
||||||
unsigned int rid;
|
unsigned int rid;
|
||||||
struct inet_peer *peer;
|
struct inet_peer *peer;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Hash table. */
|
struct inet_frags_ctl ip4_frags_ctl __read_mostly = {
|
||||||
|
/*
|
||||||
|
* Fragment cache limits. We will commit 256K at one time. Should we
|
||||||
|
* cross that limit we will prune down to 192K. This should cope with
|
||||||
|
* even the most extreme cases without allowing an attacker to
|
||||||
|
* measurably harm machine performance.
|
||||||
|
*/
|
||||||
|
.high_thresh = 256 * 1024,
|
||||||
|
.low_thresh = 192 * 1024,
|
||||||
|
|
||||||
#define IPQ_HASHSZ 64
|
/*
|
||||||
|
* Important NOTE! Fragment queue must be destroyed before MSL expires.
|
||||||
|
* RFC791 is wrong proposing to prolongate timer each fragment arrival
|
||||||
|
* by TTL.
|
||||||
|
*/
|
||||||
|
.timeout = IP_FRAG_TIME,
|
||||||
|
.secret_interval = 10 * 60 * HZ,
|
||||||
|
};
|
||||||
|
|
||||||
/* Per-bucket lock is easy to add now. */
|
static struct inet_frags ip4_frags;
|
||||||
static struct hlist_head ipq_hash[IPQ_HASHSZ];
|
|
||||||
static DEFINE_RWLOCK(ipfrag_lock);
|
|
||||||
static u32 ipfrag_hash_rnd;
|
|
||||||
static LIST_HEAD(ipq_lru_list);
|
|
||||||
int ip_frag_nqueues = 0;
|
|
||||||
|
|
||||||
static __inline__ void __ipq_unlink(struct ipq *qp)
|
int ip_frag_nqueues(void)
|
||||||
{
|
{
|
||||||
hlist_del(&qp->list);
|
return ip4_frags.nqueues;
|
||||||
list_del(&qp->lru_list);
|
|
||||||
ip_frag_nqueues--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline__ void ipq_unlink(struct ipq *ipq)
|
int ip_frag_mem(void)
|
||||||
{
|
{
|
||||||
write_lock(&ipfrag_lock);
|
return atomic_read(&ip4_frags.mem);
|
||||||
__ipq_unlink(ipq);
|
|
||||||
write_unlock(&ipfrag_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
|
||||||
|
struct net_device *dev);
|
||||||
|
|
||||||
static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot)
|
static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot)
|
||||||
{
|
{
|
||||||
return jhash_3words((__force u32)id << 16 | prot,
|
return jhash_3words((__force u32)id << 16 | prot,
|
||||||
(__force u32)saddr, (__force u32)daddr,
|
(__force u32)saddr, (__force u32)daddr,
|
||||||
ipfrag_hash_rnd) & (IPQ_HASHSZ - 1);
|
ip4_frags.rnd) & (INETFRAGS_HASHSZ - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct timer_list ipfrag_secret_timer;
|
static unsigned int ip4_hashfn(struct inet_frag_queue *q)
|
||||||
int sysctl_ipfrag_secret_interval __read_mostly = 10 * 60 * HZ;
|
|
||||||
|
|
||||||
static void ipfrag_secret_rebuild(unsigned long dummy)
|
|
||||||
{
|
{
|
||||||
unsigned long now = jiffies;
|
struct ipq *ipq;
|
||||||
int i;
|
|
||||||
|
|
||||||
write_lock(&ipfrag_lock);
|
ipq = container_of(q, struct ipq, q);
|
||||||
get_random_bytes(&ipfrag_hash_rnd, sizeof(u32));
|
return ipqhashfn(ipq->id, ipq->saddr, ipq->daddr, ipq->protocol);
|
||||||
for (i = 0; i < IPQ_HASHSZ; i++) {
|
|
||||||
struct ipq *q;
|
|
||||||
struct hlist_node *p, *n;
|
|
||||||
|
|
||||||
hlist_for_each_entry_safe(q, p, n, &ipq_hash[i], list) {
|
|
||||||
unsigned int hval = ipqhashfn(q->id, q->saddr,
|
|
||||||
q->daddr, q->protocol);
|
|
||||||
|
|
||||||
if (hval != i) {
|
|
||||||
hlist_del(&q->list);
|
|
||||||
|
|
||||||
/* Relink to new hash chain. */
|
|
||||||
hlist_add_head(&q->list, &ipq_hash[hval]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
write_unlock(&ipfrag_lock);
|
|
||||||
|
|
||||||
mod_timer(&ipfrag_secret_timer, now + sysctl_ipfrag_secret_interval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
atomic_t ip_frag_mem = ATOMIC_INIT(0); /* Memory used for fragments */
|
|
||||||
|
|
||||||
/* Memory Tracking Functions. */
|
/* Memory Tracking Functions. */
|
||||||
static __inline__ void frag_kfree_skb(struct sk_buff *skb, int *work)
|
static __inline__ void frag_kfree_skb(struct sk_buff *skb, int *work)
|
||||||
{
|
{
|
||||||
if (work)
|
if (work)
|
||||||
*work -= skb->truesize;
|
*work -= skb->truesize;
|
||||||
atomic_sub(skb->truesize, &ip_frag_mem);
|
atomic_sub(skb->truesize, &ip4_frags.mem);
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline__ void frag_free_queue(struct ipq *qp, int *work)
|
static __inline__ void ip4_frag_free(struct inet_frag_queue *q)
|
||||||
{
|
{
|
||||||
if (work)
|
struct ipq *qp;
|
||||||
*work -= sizeof(struct ipq);
|
|
||||||
atomic_sub(sizeof(struct ipq), &ip_frag_mem);
|
qp = container_of(q, struct ipq, q);
|
||||||
|
if (qp->peer)
|
||||||
|
inet_putpeer(qp->peer);
|
||||||
kfree(qp);
|
kfree(qp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline__ struct ipq *frag_alloc_queue(void)
|
static __inline__ struct ipq *frag_alloc_queue(void)
|
||||||
{
|
{
|
||||||
struct ipq *qp = kmalloc(sizeof(struct ipq), GFP_ATOMIC);
|
struct ipq *qp = kzalloc(sizeof(struct ipq), GFP_ATOMIC);
|
||||||
|
|
||||||
if (!qp)
|
if (!qp)
|
||||||
return NULL;
|
return NULL;
|
||||||
atomic_add(sizeof(struct ipq), &ip_frag_mem);
|
atomic_add(sizeof(struct ipq), &ip4_frags.mem);
|
||||||
return qp;
|
return qp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Destruction primitives. */
|
/* Destruction primitives. */
|
||||||
|
|
||||||
/* Complete destruction of ipq. */
|
static __inline__ void ipq_put(struct ipq *ipq)
|
||||||
static void ip_frag_destroy(struct ipq *qp, int *work)
|
|
||||||
{
|
{
|
||||||
struct sk_buff *fp;
|
inet_frag_put(&ipq->q, &ip4_frags);
|
||||||
|
|
||||||
BUG_TRAP(qp->last_in&COMPLETE);
|
|
||||||
BUG_TRAP(del_timer(&qp->timer) == 0);
|
|
||||||
|
|
||||||
if (qp->peer)
|
|
||||||
inet_putpeer(qp->peer);
|
|
||||||
|
|
||||||
/* Release all fragment data. */
|
|
||||||
fp = qp->fragments;
|
|
||||||
while (fp) {
|
|
||||||
struct sk_buff *xp = fp->next;
|
|
||||||
|
|
||||||
frag_kfree_skb(fp, work);
|
|
||||||
fp = xp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finally, release the queue descriptor itself. */
|
|
||||||
frag_free_queue(qp, work);
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ void ipq_put(struct ipq *ipq, int *work)
|
|
||||||
{
|
|
||||||
if (atomic_dec_and_test(&ipq->refcnt))
|
|
||||||
ip_frag_destroy(ipq, work);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Kill ipq entry. It is not destroyed immediately,
|
/* Kill ipq entry. It is not destroyed immediately,
|
||||||
@ -228,14 +165,7 @@ static __inline__ void ipq_put(struct ipq *ipq, int *work)
|
|||||||
*/
|
*/
|
||||||
static void ipq_kill(struct ipq *ipq)
|
static void ipq_kill(struct ipq *ipq)
|
||||||
{
|
{
|
||||||
if (del_timer(&ipq->timer))
|
inet_frag_kill(&ipq->q, &ip4_frags);
|
||||||
atomic_dec(&ipq->refcnt);
|
|
||||||
|
|
||||||
if (!(ipq->last_in & COMPLETE)) {
|
|
||||||
ipq_unlink(ipq);
|
|
||||||
atomic_dec(&ipq->refcnt);
|
|
||||||
ipq->last_in |= COMPLETE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Memory limiting on fragments. Evictor trashes the oldest
|
/* Memory limiting on fragments. Evictor trashes the oldest
|
||||||
@ -243,33 +173,11 @@ static void ipq_kill(struct ipq *ipq)
|
|||||||
*/
|
*/
|
||||||
static void ip_evictor(void)
|
static void ip_evictor(void)
|
||||||
{
|
{
|
||||||
struct ipq *qp;
|
int evicted;
|
||||||
struct list_head *tmp;
|
|
||||||
int work;
|
|
||||||
|
|
||||||
work = atomic_read(&ip_frag_mem) - sysctl_ipfrag_low_thresh;
|
evicted = inet_frag_evictor(&ip4_frags);
|
||||||
if (work <= 0)
|
if (evicted)
|
||||||
return;
|
IP_ADD_STATS_BH(IPSTATS_MIB_REASMFAILS, evicted);
|
||||||
|
|
||||||
while (work > 0) {
|
|
||||||
read_lock(&ipfrag_lock);
|
|
||||||
if (list_empty(&ipq_lru_list)) {
|
|
||||||
read_unlock(&ipfrag_lock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tmp = ipq_lru_list.next;
|
|
||||||
qp = list_entry(tmp, struct ipq, lru_list);
|
|
||||||
atomic_inc(&qp->refcnt);
|
|
||||||
read_unlock(&ipfrag_lock);
|
|
||||||
|
|
||||||
spin_lock(&qp->lock);
|
|
||||||
if (!(qp->last_in&COMPLETE))
|
|
||||||
ipq_kill(qp);
|
|
||||||
spin_unlock(&qp->lock);
|
|
||||||
|
|
||||||
ipq_put(qp, &work);
|
|
||||||
IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -279,9 +187,9 @@ static void ip_expire(unsigned long arg)
|
|||||||
{
|
{
|
||||||
struct ipq *qp = (struct ipq *) arg;
|
struct ipq *qp = (struct ipq *) arg;
|
||||||
|
|
||||||
spin_lock(&qp->lock);
|
spin_lock(&qp->q.lock);
|
||||||
|
|
||||||
if (qp->last_in & COMPLETE)
|
if (qp->q.last_in & COMPLETE)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ipq_kill(qp);
|
ipq_kill(qp);
|
||||||
@ -289,8 +197,8 @@ static void ip_expire(unsigned long arg)
|
|||||||
IP_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT);
|
IP_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT);
|
||||||
IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
|
IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
|
||||||
|
|
||||||
if ((qp->last_in&FIRST_IN) && qp->fragments != NULL) {
|
if ((qp->q.last_in&FIRST_IN) && qp->q.fragments != NULL) {
|
||||||
struct sk_buff *head = qp->fragments;
|
struct sk_buff *head = qp->q.fragments;
|
||||||
/* Send an ICMP "Fragment Reassembly Timeout" message. */
|
/* Send an ICMP "Fragment Reassembly Timeout" message. */
|
||||||
if ((head->dev = dev_get_by_index(&init_net, qp->iif)) != NULL) {
|
if ((head->dev = dev_get_by_index(&init_net, qp->iif)) != NULL) {
|
||||||
icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
|
icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
|
||||||
@ -298,8 +206,8 @@ static void ip_expire(unsigned long arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
spin_unlock(&qp->lock);
|
spin_unlock(&qp->q.lock);
|
||||||
ipq_put(qp, NULL);
|
ipq_put(qp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Creation primitives. */
|
/* Creation primitives. */
|
||||||
@ -312,7 +220,7 @@ static struct ipq *ip_frag_intern(struct ipq *qp_in)
|
|||||||
#endif
|
#endif
|
||||||
unsigned int hash;
|
unsigned int hash;
|
||||||
|
|
||||||
write_lock(&ipfrag_lock);
|
write_lock(&ip4_frags.lock);
|
||||||
hash = ipqhashfn(qp_in->id, qp_in->saddr, qp_in->daddr,
|
hash = ipqhashfn(qp_in->id, qp_in->saddr, qp_in->daddr,
|
||||||
qp_in->protocol);
|
qp_in->protocol);
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
@ -320,31 +228,31 @@ static struct ipq *ip_frag_intern(struct ipq *qp_in)
|
|||||||
* such entry could be created on other cpu, while we
|
* such entry could be created on other cpu, while we
|
||||||
* promoted read lock to write lock.
|
* promoted read lock to write lock.
|
||||||
*/
|
*/
|
||||||
hlist_for_each_entry(qp, n, &ipq_hash[hash], list) {
|
hlist_for_each_entry(qp, n, &ip4_frags.hash[hash], q.list) {
|
||||||
if (qp->id == qp_in->id &&
|
if (qp->id == qp_in->id &&
|
||||||
qp->saddr == qp_in->saddr &&
|
qp->saddr == qp_in->saddr &&
|
||||||
qp->daddr == qp_in->daddr &&
|
qp->daddr == qp_in->daddr &&
|
||||||
qp->protocol == qp_in->protocol &&
|
qp->protocol == qp_in->protocol &&
|
||||||
qp->user == qp_in->user) {
|
qp->user == qp_in->user) {
|
||||||
atomic_inc(&qp->refcnt);
|
atomic_inc(&qp->q.refcnt);
|
||||||
write_unlock(&ipfrag_lock);
|
write_unlock(&ip4_frags.lock);
|
||||||
qp_in->last_in |= COMPLETE;
|
qp_in->q.last_in |= COMPLETE;
|
||||||
ipq_put(qp_in, NULL);
|
ipq_put(qp_in);
|
||||||
return qp;
|
return qp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
qp = qp_in;
|
qp = qp_in;
|
||||||
|
|
||||||
if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time))
|
if (!mod_timer(&qp->q.timer, jiffies + ip4_frags_ctl.timeout))
|
||||||
atomic_inc(&qp->refcnt);
|
atomic_inc(&qp->q.refcnt);
|
||||||
|
|
||||||
atomic_inc(&qp->refcnt);
|
atomic_inc(&qp->q.refcnt);
|
||||||
hlist_add_head(&qp->list, &ipq_hash[hash]);
|
hlist_add_head(&qp->q.list, &ip4_frags.hash[hash]);
|
||||||
INIT_LIST_HEAD(&qp->lru_list);
|
INIT_LIST_HEAD(&qp->q.lru_list);
|
||||||
list_add_tail(&qp->lru_list, &ipq_lru_list);
|
list_add_tail(&qp->q.lru_list, &ip4_frags.lru_list);
|
||||||
ip_frag_nqueues++;
|
ip4_frags.nqueues++;
|
||||||
write_unlock(&ipfrag_lock);
|
write_unlock(&ip4_frags.lock);
|
||||||
return qp;
|
return qp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,23 +265,18 @@ static struct ipq *ip_frag_create(struct iphdr *iph, u32 user)
|
|||||||
goto out_nomem;
|
goto out_nomem;
|
||||||
|
|
||||||
qp->protocol = iph->protocol;
|
qp->protocol = iph->protocol;
|
||||||
qp->last_in = 0;
|
|
||||||
qp->id = iph->id;
|
qp->id = iph->id;
|
||||||
qp->saddr = iph->saddr;
|
qp->saddr = iph->saddr;
|
||||||
qp->daddr = iph->daddr;
|
qp->daddr = iph->daddr;
|
||||||
qp->user = user;
|
qp->user = user;
|
||||||
qp->len = 0;
|
|
||||||
qp->meat = 0;
|
|
||||||
qp->fragments = NULL;
|
|
||||||
qp->iif = 0;
|
|
||||||
qp->peer = sysctl_ipfrag_max_dist ? inet_getpeer(iph->saddr, 1) : NULL;
|
qp->peer = sysctl_ipfrag_max_dist ? inet_getpeer(iph->saddr, 1) : NULL;
|
||||||
|
|
||||||
/* Initialize a timer for this entry. */
|
/* Initialize a timer for this entry. */
|
||||||
init_timer(&qp->timer);
|
init_timer(&qp->q.timer);
|
||||||
qp->timer.data = (unsigned long) qp; /* pointer to queue */
|
qp->q.timer.data = (unsigned long) qp; /* pointer to queue */
|
||||||
qp->timer.function = ip_expire; /* expire function */
|
qp->q.timer.function = ip_expire; /* expire function */
|
||||||
spin_lock_init(&qp->lock);
|
spin_lock_init(&qp->q.lock);
|
||||||
atomic_set(&qp->refcnt, 1);
|
atomic_set(&qp->q.refcnt, 1);
|
||||||
|
|
||||||
return ip_frag_intern(qp);
|
return ip_frag_intern(qp);
|
||||||
|
|
||||||
@ -395,20 +298,20 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
|
|||||||
struct ipq *qp;
|
struct ipq *qp;
|
||||||
struct hlist_node *n;
|
struct hlist_node *n;
|
||||||
|
|
||||||
read_lock(&ipfrag_lock);
|
read_lock(&ip4_frags.lock);
|
||||||
hash = ipqhashfn(id, saddr, daddr, protocol);
|
hash = ipqhashfn(id, saddr, daddr, protocol);
|
||||||
hlist_for_each_entry(qp, n, &ipq_hash[hash], list) {
|
hlist_for_each_entry(qp, n, &ip4_frags.hash[hash], q.list) {
|
||||||
if (qp->id == id &&
|
if (qp->id == id &&
|
||||||
qp->saddr == saddr &&
|
qp->saddr == saddr &&
|
||||||
qp->daddr == daddr &&
|
qp->daddr == daddr &&
|
||||||
qp->protocol == protocol &&
|
qp->protocol == protocol &&
|
||||||
qp->user == user) {
|
qp->user == user) {
|
||||||
atomic_inc(&qp->refcnt);
|
atomic_inc(&qp->q.refcnt);
|
||||||
read_unlock(&ipfrag_lock);
|
read_unlock(&ip4_frags.lock);
|
||||||
return qp;
|
return qp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
read_unlock(&ipfrag_lock);
|
read_unlock(&ip4_frags.lock);
|
||||||
|
|
||||||
return ip_frag_create(iph, user);
|
return ip_frag_create(iph, user);
|
||||||
}
|
}
|
||||||
@ -429,7 +332,7 @@ static inline int ip_frag_too_far(struct ipq *qp)
|
|||||||
end = atomic_inc_return(&peer->rid);
|
end = atomic_inc_return(&peer->rid);
|
||||||
qp->rid = end;
|
qp->rid = end;
|
||||||
|
|
||||||
rc = qp->fragments && (end - start) > max;
|
rc = qp->q.fragments && (end - start) > max;
|
||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
|
IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
|
||||||
@ -442,39 +345,42 @@ static int ip_frag_reinit(struct ipq *qp)
|
|||||||
{
|
{
|
||||||
struct sk_buff *fp;
|
struct sk_buff *fp;
|
||||||
|
|
||||||
if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time)) {
|
if (!mod_timer(&qp->q.timer, jiffies + ip4_frags_ctl.timeout)) {
|
||||||
atomic_inc(&qp->refcnt);
|
atomic_inc(&qp->q.refcnt);
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
fp = qp->fragments;
|
fp = qp->q.fragments;
|
||||||
do {
|
do {
|
||||||
struct sk_buff *xp = fp->next;
|
struct sk_buff *xp = fp->next;
|
||||||
frag_kfree_skb(fp, NULL);
|
frag_kfree_skb(fp, NULL);
|
||||||
fp = xp;
|
fp = xp;
|
||||||
} while (fp);
|
} while (fp);
|
||||||
|
|
||||||
qp->last_in = 0;
|
qp->q.last_in = 0;
|
||||||
qp->len = 0;
|
qp->q.len = 0;
|
||||||
qp->meat = 0;
|
qp->q.meat = 0;
|
||||||
qp->fragments = NULL;
|
qp->q.fragments = NULL;
|
||||||
qp->iif = 0;
|
qp->iif = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add new segment to existing queue. */
|
/* Add new segment to existing queue. */
|
||||||
static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
|
static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct sk_buff *prev, *next;
|
struct sk_buff *prev, *next;
|
||||||
|
struct net_device *dev;
|
||||||
int flags, offset;
|
int flags, offset;
|
||||||
int ihl, end;
|
int ihl, end;
|
||||||
|
int err = -ENOENT;
|
||||||
|
|
||||||
if (qp->last_in & COMPLETE)
|
if (qp->q.last_in & COMPLETE)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) &&
|
if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) &&
|
||||||
unlikely(ip_frag_too_far(qp)) && unlikely(ip_frag_reinit(qp))) {
|
unlikely(ip_frag_too_far(qp)) &&
|
||||||
|
unlikely(err = ip_frag_reinit(qp))) {
|
||||||
ipq_kill(qp);
|
ipq_kill(qp);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -487,36 +393,40 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
|
|||||||
|
|
||||||
/* Determine the position of this fragment. */
|
/* Determine the position of this fragment. */
|
||||||
end = offset + skb->len - ihl;
|
end = offset + skb->len - ihl;
|
||||||
|
err = -EINVAL;
|
||||||
|
|
||||||
/* Is this the final fragment? */
|
/* Is this the final fragment? */
|
||||||
if ((flags & IP_MF) == 0) {
|
if ((flags & IP_MF) == 0) {
|
||||||
/* If we already have some bits beyond end
|
/* If we already have some bits beyond end
|
||||||
* or have different end, the segment is corrrupted.
|
* or have different end, the segment is corrrupted.
|
||||||
*/
|
*/
|
||||||
if (end < qp->len ||
|
if (end < qp->q.len ||
|
||||||
((qp->last_in & LAST_IN) && end != qp->len))
|
((qp->q.last_in & LAST_IN) && end != qp->q.len))
|
||||||
goto err;
|
goto err;
|
||||||
qp->last_in |= LAST_IN;
|
qp->q.last_in |= LAST_IN;
|
||||||
qp->len = end;
|
qp->q.len = end;
|
||||||
} else {
|
} else {
|
||||||
if (end&7) {
|
if (end&7) {
|
||||||
end &= ~7;
|
end &= ~7;
|
||||||
if (skb->ip_summed != CHECKSUM_UNNECESSARY)
|
if (skb->ip_summed != CHECKSUM_UNNECESSARY)
|
||||||
skb->ip_summed = CHECKSUM_NONE;
|
skb->ip_summed = CHECKSUM_NONE;
|
||||||
}
|
}
|
||||||
if (end > qp->len) {
|
if (end > qp->q.len) {
|
||||||
/* Some bits beyond end -> corruption. */
|
/* Some bits beyond end -> corruption. */
|
||||||
if (qp->last_in & LAST_IN)
|
if (qp->q.last_in & LAST_IN)
|
||||||
goto err;
|
goto err;
|
||||||
qp->len = end;
|
qp->q.len = end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (end == offset)
|
if (end == offset)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
err = -ENOMEM;
|
||||||
if (pskb_pull(skb, ihl) == NULL)
|
if (pskb_pull(skb, ihl) == NULL)
|
||||||
goto err;
|
goto err;
|
||||||
if (pskb_trim_rcsum(skb, end-offset))
|
|
||||||
|
err = pskb_trim_rcsum(skb, end - offset);
|
||||||
|
if (err)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* Find out which fragments are in front and at the back of us
|
/* Find out which fragments are in front and at the back of us
|
||||||
@ -524,7 +434,7 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
|
|||||||
* this fragment, right?
|
* this fragment, right?
|
||||||
*/
|
*/
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
for (next = qp->fragments; next != NULL; next = next->next) {
|
for (next = qp->q.fragments; next != NULL; next = next->next) {
|
||||||
if (FRAG_CB(next)->offset >= offset)
|
if (FRAG_CB(next)->offset >= offset)
|
||||||
break; /* bingo! */
|
break; /* bingo! */
|
||||||
prev = next;
|
prev = next;
|
||||||
@ -539,8 +449,10 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
|
|||||||
|
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
offset += i;
|
offset += i;
|
||||||
|
err = -EINVAL;
|
||||||
if (end <= offset)
|
if (end <= offset)
|
||||||
goto err;
|
goto err;
|
||||||
|
err = -ENOMEM;
|
||||||
if (!pskb_pull(skb, i))
|
if (!pskb_pull(skb, i))
|
||||||
goto err;
|
goto err;
|
||||||
if (skb->ip_summed != CHECKSUM_UNNECESSARY)
|
if (skb->ip_summed != CHECKSUM_UNNECESSARY)
|
||||||
@ -548,6 +460,8 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = -ENOMEM;
|
||||||
|
|
||||||
while (next && FRAG_CB(next)->offset < end) {
|
while (next && FRAG_CB(next)->offset < end) {
|
||||||
int i = end - FRAG_CB(next)->offset; /* overlap is 'i' bytes */
|
int i = end - FRAG_CB(next)->offset; /* overlap is 'i' bytes */
|
||||||
|
|
||||||
@ -558,7 +472,7 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
|
|||||||
if (!pskb_pull(next, i))
|
if (!pskb_pull(next, i))
|
||||||
goto err;
|
goto err;
|
||||||
FRAG_CB(next)->offset += i;
|
FRAG_CB(next)->offset += i;
|
||||||
qp->meat -= i;
|
qp->q.meat -= i;
|
||||||
if (next->ip_summed != CHECKSUM_UNNECESSARY)
|
if (next->ip_summed != CHECKSUM_UNNECESSARY)
|
||||||
next->ip_summed = CHECKSUM_NONE;
|
next->ip_summed = CHECKSUM_NONE;
|
||||||
break;
|
break;
|
||||||
@ -573,9 +487,9 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
|
|||||||
if (prev)
|
if (prev)
|
||||||
prev->next = next;
|
prev->next = next;
|
||||||
else
|
else
|
||||||
qp->fragments = next;
|
qp->q.fragments = next;
|
||||||
|
|
||||||
qp->meat -= free_it->len;
|
qp->q.meat -= free_it->len;
|
||||||
frag_kfree_skb(free_it, NULL);
|
frag_kfree_skb(free_it, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -587,50 +501,77 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
|
|||||||
if (prev)
|
if (prev)
|
||||||
prev->next = skb;
|
prev->next = skb;
|
||||||
else
|
else
|
||||||
qp->fragments = skb;
|
qp->q.fragments = skb;
|
||||||
|
|
||||||
if (skb->dev)
|
dev = skb->dev;
|
||||||
qp->iif = skb->dev->ifindex;
|
if (dev) {
|
||||||
skb->dev = NULL;
|
qp->iif = dev->ifindex;
|
||||||
qp->stamp = skb->tstamp;
|
skb->dev = NULL;
|
||||||
qp->meat += skb->len;
|
}
|
||||||
atomic_add(skb->truesize, &ip_frag_mem);
|
qp->q.stamp = skb->tstamp;
|
||||||
|
qp->q.meat += skb->len;
|
||||||
|
atomic_add(skb->truesize, &ip4_frags.mem);
|
||||||
if (offset == 0)
|
if (offset == 0)
|
||||||
qp->last_in |= FIRST_IN;
|
qp->q.last_in |= FIRST_IN;
|
||||||
|
|
||||||
write_lock(&ipfrag_lock);
|
if (qp->q.last_in == (FIRST_IN | LAST_IN) && qp->q.meat == qp->q.len)
|
||||||
list_move_tail(&qp->lru_list, &ipq_lru_list);
|
return ip_frag_reasm(qp, prev, dev);
|
||||||
write_unlock(&ipfrag_lock);
|
|
||||||
|
|
||||||
return;
|
write_lock(&ip4_frags.lock);
|
||||||
|
list_move_tail(&qp->q.lru_list, &ip4_frags.lru_list);
|
||||||
|
write_unlock(&ip4_frags.lock);
|
||||||
|
return -EINPROGRESS;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Build a new IP datagram from all its fragments. */
|
/* Build a new IP datagram from all its fragments. */
|
||||||
|
|
||||||
static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev)
|
static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
|
||||||
|
struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
struct sk_buff *fp, *head = qp->fragments;
|
struct sk_buff *fp, *head = qp->q.fragments;
|
||||||
int len;
|
int len;
|
||||||
int ihlen;
|
int ihlen;
|
||||||
|
int err;
|
||||||
|
|
||||||
ipq_kill(qp);
|
ipq_kill(qp);
|
||||||
|
|
||||||
|
/* Make the one we just received the head. */
|
||||||
|
if (prev) {
|
||||||
|
head = prev->next;
|
||||||
|
fp = skb_clone(head, GFP_ATOMIC);
|
||||||
|
|
||||||
|
if (!fp)
|
||||||
|
goto out_nomem;
|
||||||
|
|
||||||
|
fp->next = head->next;
|
||||||
|
prev->next = fp;
|
||||||
|
|
||||||
|
skb_morph(head, qp->q.fragments);
|
||||||
|
head->next = qp->q.fragments->next;
|
||||||
|
|
||||||
|
kfree_skb(qp->q.fragments);
|
||||||
|
qp->q.fragments = head;
|
||||||
|
}
|
||||||
|
|
||||||
BUG_TRAP(head != NULL);
|
BUG_TRAP(head != NULL);
|
||||||
BUG_TRAP(FRAG_CB(head)->offset == 0);
|
BUG_TRAP(FRAG_CB(head)->offset == 0);
|
||||||
|
|
||||||
/* Allocate a new buffer for the datagram. */
|
/* Allocate a new buffer for the datagram. */
|
||||||
ihlen = ip_hdrlen(head);
|
ihlen = ip_hdrlen(head);
|
||||||
len = ihlen + qp->len;
|
len = ihlen + qp->q.len;
|
||||||
|
|
||||||
|
err = -E2BIG;
|
||||||
if (len > 65535)
|
if (len > 65535)
|
||||||
goto out_oversize;
|
goto out_oversize;
|
||||||
|
|
||||||
/* Head of list must not be cloned. */
|
/* Head of list must not be cloned. */
|
||||||
|
err = -ENOMEM;
|
||||||
if (skb_cloned(head) && pskb_expand_head(head, 0, 0, GFP_ATOMIC))
|
if (skb_cloned(head) && pskb_expand_head(head, 0, 0, GFP_ATOMIC))
|
||||||
goto out_nomem;
|
goto out_nomem;
|
||||||
|
|
||||||
@ -654,12 +595,12 @@ static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev)
|
|||||||
head->len -= clone->len;
|
head->len -= clone->len;
|
||||||
clone->csum = 0;
|
clone->csum = 0;
|
||||||
clone->ip_summed = head->ip_summed;
|
clone->ip_summed = head->ip_summed;
|
||||||
atomic_add(clone->truesize, &ip_frag_mem);
|
atomic_add(clone->truesize, &ip4_frags.mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
skb_shinfo(head)->frag_list = head->next;
|
skb_shinfo(head)->frag_list = head->next;
|
||||||
skb_push(head, head->data - skb_network_header(head));
|
skb_push(head, head->data - skb_network_header(head));
|
||||||
atomic_sub(head->truesize, &ip_frag_mem);
|
atomic_sub(head->truesize, &ip4_frags.mem);
|
||||||
|
|
||||||
for (fp=head->next; fp; fp = fp->next) {
|
for (fp=head->next; fp; fp = fp->next) {
|
||||||
head->data_len += fp->len;
|
head->data_len += fp->len;
|
||||||
@ -669,19 +610,19 @@ static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev)
|
|||||||
else if (head->ip_summed == CHECKSUM_COMPLETE)
|
else if (head->ip_summed == CHECKSUM_COMPLETE)
|
||||||
head->csum = csum_add(head->csum, fp->csum);
|
head->csum = csum_add(head->csum, fp->csum);
|
||||||
head->truesize += fp->truesize;
|
head->truesize += fp->truesize;
|
||||||
atomic_sub(fp->truesize, &ip_frag_mem);
|
atomic_sub(fp->truesize, &ip4_frags.mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
head->next = NULL;
|
head->next = NULL;
|
||||||
head->dev = dev;
|
head->dev = dev;
|
||||||
head->tstamp = qp->stamp;
|
head->tstamp = qp->q.stamp;
|
||||||
|
|
||||||
iph = ip_hdr(head);
|
iph = ip_hdr(head);
|
||||||
iph->frag_off = 0;
|
iph->frag_off = 0;
|
||||||
iph->tot_len = htons(len);
|
iph->tot_len = htons(len);
|
||||||
IP_INC_STATS_BH(IPSTATS_MIB_REASMOKS);
|
IP_INC_STATS_BH(IPSTATS_MIB_REASMOKS);
|
||||||
qp->fragments = NULL;
|
qp->q.fragments = NULL;
|
||||||
return head;
|
return 0;
|
||||||
|
|
||||||
out_nomem:
|
out_nomem:
|
||||||
LIMIT_NETDEBUG(KERN_ERR "IP: queue_glue: no memory for gluing "
|
LIMIT_NETDEBUG(KERN_ERR "IP: queue_glue: no memory for gluing "
|
||||||
@ -694,54 +635,46 @@ out_oversize:
|
|||||||
NIPQUAD(qp->saddr));
|
NIPQUAD(qp->saddr));
|
||||||
out_fail:
|
out_fail:
|
||||||
IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
|
IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
|
||||||
return NULL;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process an incoming IP datagram fragment. */
|
/* Process an incoming IP datagram fragment. */
|
||||||
struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user)
|
int ip_defrag(struct sk_buff *skb, u32 user)
|
||||||
{
|
{
|
||||||
struct ipq *qp;
|
struct ipq *qp;
|
||||||
struct net_device *dev;
|
|
||||||
|
|
||||||
IP_INC_STATS_BH(IPSTATS_MIB_REASMREQDS);
|
IP_INC_STATS_BH(IPSTATS_MIB_REASMREQDS);
|
||||||
|
|
||||||
/* Start by cleaning up the memory. */
|
/* Start by cleaning up the memory. */
|
||||||
if (atomic_read(&ip_frag_mem) > sysctl_ipfrag_high_thresh)
|
if (atomic_read(&ip4_frags.mem) > ip4_frags_ctl.high_thresh)
|
||||||
ip_evictor();
|
ip_evictor();
|
||||||
|
|
||||||
dev = skb->dev;
|
|
||||||
|
|
||||||
/* Lookup (or create) queue header */
|
/* Lookup (or create) queue header */
|
||||||
if ((qp = ip_find(ip_hdr(skb), user)) != NULL) {
|
if ((qp = ip_find(ip_hdr(skb), user)) != NULL) {
|
||||||
struct sk_buff *ret = NULL;
|
int ret;
|
||||||
|
|
||||||
spin_lock(&qp->lock);
|
spin_lock(&qp->q.lock);
|
||||||
|
|
||||||
ip_frag_queue(qp, skb);
|
ret = ip_frag_queue(qp, skb);
|
||||||
|
|
||||||
if (qp->last_in == (FIRST_IN|LAST_IN) &&
|
spin_unlock(&qp->q.lock);
|
||||||
qp->meat == qp->len)
|
ipq_put(qp);
|
||||||
ret = ip_frag_reasm(qp, dev);
|
|
||||||
|
|
||||||
spin_unlock(&qp->lock);
|
|
||||||
ipq_put(qp, NULL);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
|
IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
return NULL;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init ipfrag_init(void)
|
void __init ipfrag_init(void)
|
||||||
{
|
{
|
||||||
ipfrag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
|
ip4_frags.ctl = &ip4_frags_ctl;
|
||||||
(jiffies ^ (jiffies >> 6)));
|
ip4_frags.hashfn = ip4_hashfn;
|
||||||
|
ip4_frags.destructor = ip4_frag_free;
|
||||||
init_timer(&ipfrag_secret_timer);
|
ip4_frags.skb_free = NULL;
|
||||||
ipfrag_secret_timer.function = ipfrag_secret_rebuild;
|
ip4_frags.qsize = sizeof(struct ipq);
|
||||||
ipfrag_secret_timer.expires = jiffies + sysctl_ipfrag_secret_interval;
|
inet_frags_init(&ip4_frags);
|
||||||
add_timer(&ipfrag_secret_timer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(ip_defrag);
|
EXPORT_SYMBOL(ip_defrag);
|
||||||
|
@ -172,8 +172,7 @@ int ip_call_ra_chain(struct sk_buff *skb)
|
|||||||
(!sk->sk_bound_dev_if ||
|
(!sk->sk_bound_dev_if ||
|
||||||
sk->sk_bound_dev_if == skb->dev->ifindex)) {
|
sk->sk_bound_dev_if == skb->dev->ifindex)) {
|
||||||
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
|
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
|
||||||
skb = ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN);
|
if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN)) {
|
||||||
if (skb == NULL) {
|
|
||||||
read_unlock(&ip_ra_lock);
|
read_unlock(&ip_ra_lock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -196,7 +195,7 @@ int ip_call_ra_chain(struct sk_buff *skb)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ip_local_deliver_finish(struct sk_buff *skb)
|
static int ip_local_deliver_finish(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
__skb_pull(skb, ip_hdrlen(skb));
|
__skb_pull(skb, ip_hdrlen(skb));
|
||||||
|
|
||||||
@ -265,8 +264,7 @@ int ip_local_deliver(struct sk_buff *skb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
|
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
|
||||||
skb = ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER);
|
if (ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER))
|
||||||
if (!skb)
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,7 +324,7 @@ drop:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ip_rcv_finish(struct sk_buff *skb)
|
static int ip_rcv_finish(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
const struct iphdr *iph = ip_hdr(skb);
|
const struct iphdr *iph = ip_hdr(skb);
|
||||||
struct rtable *rt;
|
struct rtable *rt;
|
||||||
|
@ -202,7 +202,7 @@ static inline int ip_skb_dst_mtu(struct sk_buff *skb)
|
|||||||
skb->dst->dev->mtu : dst_mtu(skb->dst);
|
skb->dst->dev->mtu : dst_mtu(skb->dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ip_finish_output(struct sk_buff *skb)
|
static int ip_finish_output(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)
|
#if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)
|
||||||
/* Policy lookup after SNAT yielded a new policy */
|
/* Policy lookup after SNAT yielded a new policy */
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
#include <linux/in.h>
|
#include <linux/in.h>
|
||||||
#include <linux/ip.h>
|
#include <linux/ip.h>
|
||||||
|
#include <linux/netfilter.h>
|
||||||
#include <net/net_namespace.h>
|
#include <net/net_namespace.h>
|
||||||
#include <net/protocol.h>
|
#include <net/protocol.h>
|
||||||
#include <net/tcp.h>
|
#include <net/tcp.h>
|
||||||
@ -328,18 +329,18 @@ static inline void vs_seq_update(struct ip_vs_conn *cp, struct ip_vs_seq *vseq,
|
|||||||
spin_unlock(&cp->lock);
|
spin_unlock(&cp->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb,
|
static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb,
|
||||||
struct ip_vs_app *app)
|
struct ip_vs_app *app)
|
||||||
{
|
{
|
||||||
int diff;
|
int diff;
|
||||||
const unsigned int tcp_offset = ip_hdrlen(*pskb);
|
const unsigned int tcp_offset = ip_hdrlen(skb);
|
||||||
struct tcphdr *th;
|
struct tcphdr *th;
|
||||||
__u32 seq;
|
__u32 seq;
|
||||||
|
|
||||||
if (!ip_vs_make_skb_writable(pskb, tcp_offset + sizeof(*th)))
|
if (!skb_make_writable(skb, tcp_offset + sizeof(*th)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
th = (struct tcphdr *)(skb_network_header(*pskb) + tcp_offset);
|
th = (struct tcphdr *)(skb_network_header(skb) + tcp_offset);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remember seq number in case this pkt gets resized
|
* Remember seq number in case this pkt gets resized
|
||||||
@ -360,7 +361,7 @@ static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb,
|
|||||||
if (app->pkt_out == NULL)
|
if (app->pkt_out == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!app->pkt_out(app, cp, pskb, &diff))
|
if (!app->pkt_out(app, cp, skb, &diff))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -378,7 +379,7 @@ static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb,
|
|||||||
* called by ipvs packet handler, assumes previously checked cp!=NULL
|
* called by ipvs packet handler, assumes previously checked cp!=NULL
|
||||||
* returns false if it can't handle packet (oom)
|
* returns false if it can't handle packet (oom)
|
||||||
*/
|
*/
|
||||||
int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb)
|
int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct ip_vs_app *app;
|
struct ip_vs_app *app;
|
||||||
|
|
||||||
@ -391,7 +392,7 @@ int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb)
|
|||||||
|
|
||||||
/* TCP is complicated */
|
/* TCP is complicated */
|
||||||
if (cp->protocol == IPPROTO_TCP)
|
if (cp->protocol == IPPROTO_TCP)
|
||||||
return app_tcp_pkt_out(cp, pskb, app);
|
return app_tcp_pkt_out(cp, skb, app);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call private output hook function
|
* Call private output hook function
|
||||||
@ -399,22 +400,22 @@ int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb)
|
|||||||
if (app->pkt_out == NULL)
|
if (app->pkt_out == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return app->pkt_out(app, cp, pskb, NULL);
|
return app->pkt_out(app, cp, skb, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb,
|
static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb,
|
||||||
struct ip_vs_app *app)
|
struct ip_vs_app *app)
|
||||||
{
|
{
|
||||||
int diff;
|
int diff;
|
||||||
const unsigned int tcp_offset = ip_hdrlen(*pskb);
|
const unsigned int tcp_offset = ip_hdrlen(skb);
|
||||||
struct tcphdr *th;
|
struct tcphdr *th;
|
||||||
__u32 seq;
|
__u32 seq;
|
||||||
|
|
||||||
if (!ip_vs_make_skb_writable(pskb, tcp_offset + sizeof(*th)))
|
if (!skb_make_writable(skb, tcp_offset + sizeof(*th)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
th = (struct tcphdr *)(skb_network_header(*pskb) + tcp_offset);
|
th = (struct tcphdr *)(skb_network_header(skb) + tcp_offset);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remember seq number in case this pkt gets resized
|
* Remember seq number in case this pkt gets resized
|
||||||
@ -435,7 +436,7 @@ static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb,
|
|||||||
if (app->pkt_in == NULL)
|
if (app->pkt_in == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!app->pkt_in(app, cp, pskb, &diff))
|
if (!app->pkt_in(app, cp, skb, &diff))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -453,7 +454,7 @@ static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb,
|
|||||||
* called by ipvs packet handler, assumes previously checked cp!=NULL.
|
* called by ipvs packet handler, assumes previously checked cp!=NULL.
|
||||||
* returns false if can't handle packet (oom).
|
* returns false if can't handle packet (oom).
|
||||||
*/
|
*/
|
||||||
int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb)
|
int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct ip_vs_app *app;
|
struct ip_vs_app *app;
|
||||||
|
|
||||||
@ -466,7 +467,7 @@ int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb)
|
|||||||
|
|
||||||
/* TCP is complicated */
|
/* TCP is complicated */
|
||||||
if (cp->protocol == IPPROTO_TCP)
|
if (cp->protocol == IPPROTO_TCP)
|
||||||
return app_tcp_pkt_in(cp, pskb, app);
|
return app_tcp_pkt_in(cp, skb, app);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call private input hook function
|
* Call private input hook function
|
||||||
@ -474,7 +475,7 @@ int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb)
|
|||||||
if (app->pkt_in == NULL)
|
if (app->pkt_in == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return app->pkt_in(app, cp, pskb, NULL);
|
return app->pkt_in(app, cp, skb, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,7 +58,6 @@ EXPORT_SYMBOL(ip_vs_conn_put);
|
|||||||
#ifdef CONFIG_IP_VS_DEBUG
|
#ifdef CONFIG_IP_VS_DEBUG
|
||||||
EXPORT_SYMBOL(ip_vs_get_debug_level);
|
EXPORT_SYMBOL(ip_vs_get_debug_level);
|
||||||
#endif
|
#endif
|
||||||
EXPORT_SYMBOL(ip_vs_make_skb_writable);
|
|
||||||
|
|
||||||
|
|
||||||
/* ID used in ICMP lookups */
|
/* ID used in ICMP lookups */
|
||||||
@ -163,42 +162,6 @@ ip_vs_set_state(struct ip_vs_conn *cp, int direction,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ip_vs_make_skb_writable(struct sk_buff **pskb, int writable_len)
|
|
||||||
{
|
|
||||||
struct sk_buff *skb = *pskb;
|
|
||||||
|
|
||||||
/* skb is already used, better copy skb and its payload */
|
|
||||||
if (unlikely(skb_shared(skb) || skb->sk))
|
|
||||||
goto copy_skb;
|
|
||||||
|
|
||||||
/* skb data is already used, copy it */
|
|
||||||
if (unlikely(skb_cloned(skb)))
|
|
||||||
goto copy_data;
|
|
||||||
|
|
||||||
return pskb_may_pull(skb, writable_len);
|
|
||||||
|
|
||||||
copy_data:
|
|
||||||
if (unlikely(writable_len > skb->len))
|
|
||||||
return 0;
|
|
||||||
return !pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
|
|
||||||
|
|
||||||
copy_skb:
|
|
||||||
if (unlikely(writable_len > skb->len))
|
|
||||||
return 0;
|
|
||||||
skb = skb_copy(skb, GFP_ATOMIC);
|
|
||||||
if (!skb)
|
|
||||||
return 0;
|
|
||||||
BUG_ON(skb_is_nonlinear(skb));
|
|
||||||
|
|
||||||
/* Rest of kernel will get very unhappy if we pass it a
|
|
||||||
suddenly-orphaned skbuff */
|
|
||||||
if ((*pskb)->sk)
|
|
||||||
skb_set_owner_w(skb, (*pskb)->sk);
|
|
||||||
kfree_skb(*pskb);
|
|
||||||
*pskb = skb;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IPVS persistent scheduling function
|
* IPVS persistent scheduling function
|
||||||
* It creates a connection entry according to its template if exists,
|
* It creates a connection entry according to its template if exists,
|
||||||
@ -525,12 +488,12 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
|
|||||||
* for VS/NAT.
|
* for VS/NAT.
|
||||||
*/
|
*/
|
||||||
static unsigned int ip_vs_post_routing(unsigned int hooknum,
|
static unsigned int ip_vs_post_routing(unsigned int hooknum,
|
||||||
struct sk_buff **pskb,
|
struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
if (!((*pskb)->ipvs_property))
|
if (!skb->ipvs_property)
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
/* The packet was sent from IPVS, exit this chain */
|
/* The packet was sent from IPVS, exit this chain */
|
||||||
return NF_STOP;
|
return NF_STOP;
|
||||||
@ -541,13 +504,14 @@ __sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset)
|
|||||||
return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0));
|
return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct sk_buff *
|
static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user)
|
||||||
ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user)
|
|
||||||
{
|
{
|
||||||
skb = ip_defrag(skb, user);
|
int err = ip_defrag(skb, user);
|
||||||
if (skb)
|
|
||||||
|
if (!err)
|
||||||
ip_send_check(ip_hdr(skb));
|
ip_send_check(ip_hdr(skb));
|
||||||
return skb;
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -605,9 +569,8 @@ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||||||
* Currently handles error types - unreachable, quench, ttl exceeded.
|
* Currently handles error types - unreachable, quench, ttl exceeded.
|
||||||
* (Only used in VS/NAT)
|
* (Only used in VS/NAT)
|
||||||
*/
|
*/
|
||||||
static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
|
static int ip_vs_out_icmp(struct sk_buff *skb, int *related)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb = *pskb;
|
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
struct icmphdr _icmph, *ic;
|
struct icmphdr _icmph, *ic;
|
||||||
struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */
|
struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */
|
||||||
@ -619,10 +582,8 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
|
|||||||
|
|
||||||
/* reassemble IP fragments */
|
/* reassemble IP fragments */
|
||||||
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
|
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
|
||||||
skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT);
|
if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT))
|
||||||
if (!skb)
|
|
||||||
return NF_STOLEN;
|
return NF_STOLEN;
|
||||||
*pskb = skb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iph = ip_hdr(skb);
|
iph = ip_hdr(skb);
|
||||||
@ -690,9 +651,8 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
|
|||||||
|
|
||||||
if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
|
if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
|
||||||
offset += 2 * sizeof(__u16);
|
offset += 2 * sizeof(__u16);
|
||||||
if (!ip_vs_make_skb_writable(pskb, offset))
|
if (!skb_make_writable(skb, offset))
|
||||||
goto out;
|
goto out;
|
||||||
skb = *pskb;
|
|
||||||
|
|
||||||
ip_vs_nat_icmp(skb, pp, cp, 1);
|
ip_vs_nat_icmp(skb, pp, cp, 1);
|
||||||
|
|
||||||
@ -724,11 +684,10 @@ static inline int is_tcp_reset(const struct sk_buff *skb)
|
|||||||
* rewrite addresses of the packet and send it on its way...
|
* rewrite addresses of the packet and send it on its way...
|
||||||
*/
|
*/
|
||||||
static unsigned int
|
static unsigned int
|
||||||
ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
|
ip_vs_out(unsigned int hooknum, struct sk_buff *skb,
|
||||||
const struct net_device *in, const struct net_device *out,
|
const struct net_device *in, const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
struct sk_buff *skb = *pskb;
|
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
struct ip_vs_protocol *pp;
|
struct ip_vs_protocol *pp;
|
||||||
struct ip_vs_conn *cp;
|
struct ip_vs_conn *cp;
|
||||||
@ -741,11 +700,10 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
|
|||||||
|
|
||||||
iph = ip_hdr(skb);
|
iph = ip_hdr(skb);
|
||||||
if (unlikely(iph->protocol == IPPROTO_ICMP)) {
|
if (unlikely(iph->protocol == IPPROTO_ICMP)) {
|
||||||
int related, verdict = ip_vs_out_icmp(pskb, &related);
|
int related, verdict = ip_vs_out_icmp(skb, &related);
|
||||||
|
|
||||||
if (related)
|
if (related)
|
||||||
return verdict;
|
return verdict;
|
||||||
skb = *pskb;
|
|
||||||
iph = ip_hdr(skb);
|
iph = ip_hdr(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -756,11 +714,9 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
|
|||||||
/* reassemble IP fragments */
|
/* reassemble IP fragments */
|
||||||
if (unlikely(iph->frag_off & htons(IP_MF|IP_OFFSET) &&
|
if (unlikely(iph->frag_off & htons(IP_MF|IP_OFFSET) &&
|
||||||
!pp->dont_defrag)) {
|
!pp->dont_defrag)) {
|
||||||
skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT);
|
if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT))
|
||||||
if (!skb)
|
|
||||||
return NF_STOLEN;
|
return NF_STOLEN;
|
||||||
iph = ip_hdr(skb);
|
iph = ip_hdr(skb);
|
||||||
*pskb = skb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ihl = iph->ihl << 2;
|
ihl = iph->ihl << 2;
|
||||||
@ -802,13 +758,12 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
|
|||||||
|
|
||||||
IP_VS_DBG_PKT(11, pp, skb, 0, "Outgoing packet");
|
IP_VS_DBG_PKT(11, pp, skb, 0, "Outgoing packet");
|
||||||
|
|
||||||
if (!ip_vs_make_skb_writable(pskb, ihl))
|
if (!skb_make_writable(skb, ihl))
|
||||||
goto drop;
|
goto drop;
|
||||||
|
|
||||||
/* mangle the packet */
|
/* mangle the packet */
|
||||||
if (pp->snat_handler && !pp->snat_handler(pskb, pp, cp))
|
if (pp->snat_handler && !pp->snat_handler(skb, pp, cp))
|
||||||
goto drop;
|
goto drop;
|
||||||
skb = *pskb;
|
|
||||||
ip_hdr(skb)->saddr = cp->vaddr;
|
ip_hdr(skb)->saddr = cp->vaddr;
|
||||||
ip_send_check(ip_hdr(skb));
|
ip_send_check(ip_hdr(skb));
|
||||||
|
|
||||||
@ -818,9 +773,8 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
|
|||||||
* if it came from this machine itself. So re-compute
|
* if it came from this machine itself. So re-compute
|
||||||
* the routing information.
|
* the routing information.
|
||||||
*/
|
*/
|
||||||
if (ip_route_me_harder(pskb, RTN_LOCAL) != 0)
|
if (ip_route_me_harder(skb, RTN_LOCAL) != 0)
|
||||||
goto drop;
|
goto drop;
|
||||||
skb = *pskb;
|
|
||||||
|
|
||||||
IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT");
|
IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT");
|
||||||
|
|
||||||
@ -835,7 +789,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
|
|||||||
|
|
||||||
drop:
|
drop:
|
||||||
ip_vs_conn_put(cp);
|
ip_vs_conn_put(cp);
|
||||||
kfree_skb(*pskb);
|
kfree_skb(skb);
|
||||||
return NF_STOLEN;
|
return NF_STOLEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -847,9 +801,8 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
|
|||||||
* Currently handles error types - unreachable, quench, ttl exceeded.
|
* Currently handles error types - unreachable, quench, ttl exceeded.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum)
|
ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb = *pskb;
|
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
struct icmphdr _icmph, *ic;
|
struct icmphdr _icmph, *ic;
|
||||||
struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */
|
struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */
|
||||||
@ -861,12 +814,9 @@ ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum)
|
|||||||
|
|
||||||
/* reassemble IP fragments */
|
/* reassemble IP fragments */
|
||||||
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
|
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
|
||||||
skb = ip_vs_gather_frags(skb,
|
if (ip_vs_gather_frags(skb, hooknum == NF_IP_LOCAL_IN ?
|
||||||
hooknum == NF_IP_LOCAL_IN ?
|
IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD))
|
||||||
IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD);
|
|
||||||
if (!skb)
|
|
||||||
return NF_STOLEN;
|
return NF_STOLEN;
|
||||||
*pskb = skb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iph = ip_hdr(skb);
|
iph = ip_hdr(skb);
|
||||||
@ -945,11 +895,10 @@ ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum)
|
|||||||
* and send it on its way...
|
* and send it on its way...
|
||||||
*/
|
*/
|
||||||
static unsigned int
|
static unsigned int
|
||||||
ip_vs_in(unsigned int hooknum, struct sk_buff **pskb,
|
ip_vs_in(unsigned int hooknum, struct sk_buff *skb,
|
||||||
const struct net_device *in, const struct net_device *out,
|
const struct net_device *in, const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
struct sk_buff *skb = *pskb;
|
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
struct ip_vs_protocol *pp;
|
struct ip_vs_protocol *pp;
|
||||||
struct ip_vs_conn *cp;
|
struct ip_vs_conn *cp;
|
||||||
@ -971,11 +920,10 @@ ip_vs_in(unsigned int hooknum, struct sk_buff **pskb,
|
|||||||
|
|
||||||
iph = ip_hdr(skb);
|
iph = ip_hdr(skb);
|
||||||
if (unlikely(iph->protocol == IPPROTO_ICMP)) {
|
if (unlikely(iph->protocol == IPPROTO_ICMP)) {
|
||||||
int related, verdict = ip_vs_in_icmp(pskb, &related, hooknum);
|
int related, verdict = ip_vs_in_icmp(skb, &related, hooknum);
|
||||||
|
|
||||||
if (related)
|
if (related)
|
||||||
return verdict;
|
return verdict;
|
||||||
skb = *pskb;
|
|
||||||
iph = ip_hdr(skb);
|
iph = ip_hdr(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1056,16 +1004,16 @@ ip_vs_in(unsigned int hooknum, struct sk_buff **pskb,
|
|||||||
* and send them to ip_vs_in_icmp.
|
* and send them to ip_vs_in_icmp.
|
||||||
*/
|
*/
|
||||||
static unsigned int
|
static unsigned int
|
||||||
ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff **pskb,
|
ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb,
|
||||||
const struct net_device *in, const struct net_device *out,
|
const struct net_device *in, const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (ip_hdr(*pskb)->protocol != IPPROTO_ICMP)
|
if (ip_hdr(skb)->protocol != IPPROTO_ICMP)
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
|
|
||||||
return ip_vs_in_icmp(pskb, &r, hooknum);
|
return ip_vs_in_icmp(skb, &r, hooknum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
#include <linux/in.h>
|
#include <linux/in.h>
|
||||||
#include <linux/ip.h>
|
#include <linux/ip.h>
|
||||||
|
#include <linux/netfilter.h>
|
||||||
#include <net/protocol.h>
|
#include <net/protocol.h>
|
||||||
#include <net/tcp.h>
|
#include <net/tcp.h>
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
@ -135,7 +136,7 @@ static int ip_vs_ftp_get_addrport(char *data, char *data_limit,
|
|||||||
* xxx,xxx,xxx,xxx is the server address, ppp,ppp is the server port number.
|
* xxx,xxx,xxx,xxx is the server address, ppp,ppp is the server port number.
|
||||||
*/
|
*/
|
||||||
static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
|
static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
|
||||||
struct sk_buff **pskb, int *diff)
|
struct sk_buff *skb, int *diff)
|
||||||
{
|
{
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
struct tcphdr *th;
|
struct tcphdr *th;
|
||||||
@ -155,14 +156,14 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Linear packets are much easier to deal with. */
|
/* Linear packets are much easier to deal with. */
|
||||||
if (!ip_vs_make_skb_writable(pskb, (*pskb)->len))
|
if (!skb_make_writable(skb, skb->len))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (cp->app_data == &ip_vs_ftp_pasv) {
|
if (cp->app_data == &ip_vs_ftp_pasv) {
|
||||||
iph = ip_hdr(*pskb);
|
iph = ip_hdr(skb);
|
||||||
th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
|
th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
|
||||||
data = (char *)th + (th->doff << 2);
|
data = (char *)th + (th->doff << 2);
|
||||||
data_limit = skb_tail_pointer(*pskb);
|
data_limit = skb_tail_pointer(skb);
|
||||||
|
|
||||||
if (ip_vs_ftp_get_addrport(data, data_limit,
|
if (ip_vs_ftp_get_addrport(data, data_limit,
|
||||||
SERVER_STRING,
|
SERVER_STRING,
|
||||||
@ -213,7 +214,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
|
|||||||
memcpy(start, buf, buf_len);
|
memcpy(start, buf, buf_len);
|
||||||
ret = 1;
|
ret = 1;
|
||||||
} else {
|
} else {
|
||||||
ret = !ip_vs_skb_replace(*pskb, GFP_ATOMIC, start,
|
ret = !ip_vs_skb_replace(skb, GFP_ATOMIC, start,
|
||||||
end-start, buf, buf_len);
|
end-start, buf, buf_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,7 +239,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
|
|||||||
* the client.
|
* the client.
|
||||||
*/
|
*/
|
||||||
static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
|
static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
|
||||||
struct sk_buff **pskb, int *diff)
|
struct sk_buff *skb, int *diff)
|
||||||
{
|
{
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
struct tcphdr *th;
|
struct tcphdr *th;
|
||||||
@ -256,20 +257,20 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Linear packets are much easier to deal with. */
|
/* Linear packets are much easier to deal with. */
|
||||||
if (!ip_vs_make_skb_writable(pskb, (*pskb)->len))
|
if (!skb_make_writable(skb, skb->len))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Detecting whether it is passive
|
* Detecting whether it is passive
|
||||||
*/
|
*/
|
||||||
iph = ip_hdr(*pskb);
|
iph = ip_hdr(skb);
|
||||||
th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
|
th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
|
||||||
|
|
||||||
/* Since there may be OPTIONS in the TCP packet and the HLEN is
|
/* Since there may be OPTIONS in the TCP packet and the HLEN is
|
||||||
the length of the header in 32-bit multiples, it is accurate
|
the length of the header in 32-bit multiples, it is accurate
|
||||||
to calculate data address by th+HLEN*4 */
|
to calculate data address by th+HLEN*4 */
|
||||||
data = data_start = (char *)th + (th->doff << 2);
|
data = data_start = (char *)th + (th->doff << 2);
|
||||||
data_limit = skb_tail_pointer(*pskb);
|
data_limit = skb_tail_pointer(skb);
|
||||||
|
|
||||||
while (data <= data_limit - 6) {
|
while (data <= data_limit - 6) {
|
||||||
if (strnicmp(data, "PASV\r\n", 6) == 0) {
|
if (strnicmp(data, "PASV\r\n", 6) == 0) {
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <linux/tcp.h> /* for tcphdr */
|
#include <linux/tcp.h> /* for tcphdr */
|
||||||
#include <net/ip.h>
|
#include <net/ip.h>
|
||||||
#include <net/tcp.h> /* for csum_tcpudp_magic */
|
#include <net/tcp.h> /* for csum_tcpudp_magic */
|
||||||
|
#include <linux/netfilter.h>
|
||||||
#include <linux/netfilter_ipv4.h>
|
#include <linux/netfilter_ipv4.h>
|
||||||
|
|
||||||
#include <net/ip_vs.h>
|
#include <net/ip_vs.h>
|
||||||
@ -122,27 +123,27 @@ tcp_fast_csum_update(struct tcphdr *tcph, __be32 oldip, __be32 newip,
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
tcp_snat_handler(struct sk_buff **pskb,
|
tcp_snat_handler(struct sk_buff *skb,
|
||||||
struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
|
struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
|
||||||
{
|
{
|
||||||
struct tcphdr *tcph;
|
struct tcphdr *tcph;
|
||||||
const unsigned int tcphoff = ip_hdrlen(*pskb);
|
const unsigned int tcphoff = ip_hdrlen(skb);
|
||||||
|
|
||||||
/* csum_check requires unshared skb */
|
/* csum_check requires unshared skb */
|
||||||
if (!ip_vs_make_skb_writable(pskb, tcphoff+sizeof(*tcph)))
|
if (!skb_make_writable(skb, tcphoff+sizeof(*tcph)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (unlikely(cp->app != NULL)) {
|
if (unlikely(cp->app != NULL)) {
|
||||||
/* Some checks before mangling */
|
/* Some checks before mangling */
|
||||||
if (pp->csum_check && !pp->csum_check(*pskb, pp))
|
if (pp->csum_check && !pp->csum_check(skb, pp))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Call application helper if needed */
|
/* Call application helper if needed */
|
||||||
if (!ip_vs_app_pkt_out(cp, pskb))
|
if (!ip_vs_app_pkt_out(cp, skb))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcph = (void *)ip_hdr(*pskb) + tcphoff;
|
tcph = (void *)ip_hdr(skb) + tcphoff;
|
||||||
tcph->source = cp->vport;
|
tcph->source = cp->vport;
|
||||||
|
|
||||||
/* Adjust TCP checksums */
|
/* Adjust TCP checksums */
|
||||||
@ -150,17 +151,15 @@ tcp_snat_handler(struct sk_buff **pskb,
|
|||||||
/* Only port and addr are changed, do fast csum update */
|
/* Only port and addr are changed, do fast csum update */
|
||||||
tcp_fast_csum_update(tcph, cp->daddr, cp->vaddr,
|
tcp_fast_csum_update(tcph, cp->daddr, cp->vaddr,
|
||||||
cp->dport, cp->vport);
|
cp->dport, cp->vport);
|
||||||
if ((*pskb)->ip_summed == CHECKSUM_COMPLETE)
|
if (skb->ip_summed == CHECKSUM_COMPLETE)
|
||||||
(*pskb)->ip_summed = CHECKSUM_NONE;
|
skb->ip_summed = CHECKSUM_NONE;
|
||||||
} else {
|
} else {
|
||||||
/* full checksum calculation */
|
/* full checksum calculation */
|
||||||
tcph->check = 0;
|
tcph->check = 0;
|
||||||
(*pskb)->csum = skb_checksum(*pskb, tcphoff,
|
skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0);
|
||||||
(*pskb)->len - tcphoff, 0);
|
|
||||||
tcph->check = csum_tcpudp_magic(cp->vaddr, cp->caddr,
|
tcph->check = csum_tcpudp_magic(cp->vaddr, cp->caddr,
|
||||||
(*pskb)->len - tcphoff,
|
skb->len - tcphoff,
|
||||||
cp->protocol,
|
cp->protocol, skb->csum);
|
||||||
(*pskb)->csum);
|
|
||||||
IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n",
|
IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n",
|
||||||
pp->name, tcph->check,
|
pp->name, tcph->check,
|
||||||
(char*)&(tcph->check) - (char*)tcph);
|
(char*)&(tcph->check) - (char*)tcph);
|
||||||
@ -170,30 +169,30 @@ tcp_snat_handler(struct sk_buff **pskb,
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
tcp_dnat_handler(struct sk_buff **pskb,
|
tcp_dnat_handler(struct sk_buff *skb,
|
||||||
struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
|
struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
|
||||||
{
|
{
|
||||||
struct tcphdr *tcph;
|
struct tcphdr *tcph;
|
||||||
const unsigned int tcphoff = ip_hdrlen(*pskb);
|
const unsigned int tcphoff = ip_hdrlen(skb);
|
||||||
|
|
||||||
/* csum_check requires unshared skb */
|
/* csum_check requires unshared skb */
|
||||||
if (!ip_vs_make_skb_writable(pskb, tcphoff+sizeof(*tcph)))
|
if (!skb_make_writable(skb, tcphoff+sizeof(*tcph)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (unlikely(cp->app != NULL)) {
|
if (unlikely(cp->app != NULL)) {
|
||||||
/* Some checks before mangling */
|
/* Some checks before mangling */
|
||||||
if (pp->csum_check && !pp->csum_check(*pskb, pp))
|
if (pp->csum_check && !pp->csum_check(skb, pp))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attempt ip_vs_app call.
|
* Attempt ip_vs_app call.
|
||||||
* It will fix ip_vs_conn and iph ack_seq stuff
|
* It will fix ip_vs_conn and iph ack_seq stuff
|
||||||
*/
|
*/
|
||||||
if (!ip_vs_app_pkt_in(cp, pskb))
|
if (!ip_vs_app_pkt_in(cp, skb))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcph = (void *)ip_hdr(*pskb) + tcphoff;
|
tcph = (void *)ip_hdr(skb) + tcphoff;
|
||||||
tcph->dest = cp->dport;
|
tcph->dest = cp->dport;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -203,18 +202,16 @@ tcp_dnat_handler(struct sk_buff **pskb,
|
|||||||
/* Only port and addr are changed, do fast csum update */
|
/* Only port and addr are changed, do fast csum update */
|
||||||
tcp_fast_csum_update(tcph, cp->vaddr, cp->daddr,
|
tcp_fast_csum_update(tcph, cp->vaddr, cp->daddr,
|
||||||
cp->vport, cp->dport);
|
cp->vport, cp->dport);
|
||||||
if ((*pskb)->ip_summed == CHECKSUM_COMPLETE)
|
if (skb->ip_summed == CHECKSUM_COMPLETE)
|
||||||
(*pskb)->ip_summed = CHECKSUM_NONE;
|
skb->ip_summed = CHECKSUM_NONE;
|
||||||
} else {
|
} else {
|
||||||
/* full checksum calculation */
|
/* full checksum calculation */
|
||||||
tcph->check = 0;
|
tcph->check = 0;
|
||||||
(*pskb)->csum = skb_checksum(*pskb, tcphoff,
|
skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0);
|
||||||
(*pskb)->len - tcphoff, 0);
|
|
||||||
tcph->check = csum_tcpudp_magic(cp->caddr, cp->daddr,
|
tcph->check = csum_tcpudp_magic(cp->caddr, cp->daddr,
|
||||||
(*pskb)->len - tcphoff,
|
skb->len - tcphoff,
|
||||||
cp->protocol,
|
cp->protocol, skb->csum);
|
||||||
(*pskb)->csum);
|
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||||
(*pskb)->ip_summed = CHECKSUM_UNNECESSARY;
|
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <linux/in.h>
|
#include <linux/in.h>
|
||||||
#include <linux/ip.h>
|
#include <linux/ip.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/netfilter.h>
|
||||||
#include <linux/netfilter_ipv4.h>
|
#include <linux/netfilter_ipv4.h>
|
||||||
#include <linux/udp.h>
|
#include <linux/udp.h>
|
||||||
|
|
||||||
@ -129,29 +130,29 @@ udp_fast_csum_update(struct udphdr *uhdr, __be32 oldip, __be32 newip,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
udp_snat_handler(struct sk_buff **pskb,
|
udp_snat_handler(struct sk_buff *skb,
|
||||||
struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
|
struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
|
||||||
{
|
{
|
||||||
struct udphdr *udph;
|
struct udphdr *udph;
|
||||||
const unsigned int udphoff = ip_hdrlen(*pskb);
|
const unsigned int udphoff = ip_hdrlen(skb);
|
||||||
|
|
||||||
/* csum_check requires unshared skb */
|
/* csum_check requires unshared skb */
|
||||||
if (!ip_vs_make_skb_writable(pskb, udphoff+sizeof(*udph)))
|
if (!skb_make_writable(skb, udphoff+sizeof(*udph)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (unlikely(cp->app != NULL)) {
|
if (unlikely(cp->app != NULL)) {
|
||||||
/* Some checks before mangling */
|
/* Some checks before mangling */
|
||||||
if (pp->csum_check && !pp->csum_check(*pskb, pp))
|
if (pp->csum_check && !pp->csum_check(skb, pp))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call application helper if needed
|
* Call application helper if needed
|
||||||
*/
|
*/
|
||||||
if (!ip_vs_app_pkt_out(cp, pskb))
|
if (!ip_vs_app_pkt_out(cp, skb))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
udph = (void *)ip_hdr(*pskb) + udphoff;
|
udph = (void *)ip_hdr(skb) + udphoff;
|
||||||
udph->source = cp->vport;
|
udph->source = cp->vport;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -161,17 +162,15 @@ udp_snat_handler(struct sk_buff **pskb,
|
|||||||
/* Only port and addr are changed, do fast csum update */
|
/* Only port and addr are changed, do fast csum update */
|
||||||
udp_fast_csum_update(udph, cp->daddr, cp->vaddr,
|
udp_fast_csum_update(udph, cp->daddr, cp->vaddr,
|
||||||
cp->dport, cp->vport);
|
cp->dport, cp->vport);
|
||||||
if ((*pskb)->ip_summed == CHECKSUM_COMPLETE)
|
if (skb->ip_summed == CHECKSUM_COMPLETE)
|
||||||
(*pskb)->ip_summed = CHECKSUM_NONE;
|
skb->ip_summed = CHECKSUM_NONE;
|
||||||
} else {
|
} else {
|
||||||
/* full checksum calculation */
|
/* full checksum calculation */
|
||||||
udph->check = 0;
|
udph->check = 0;
|
||||||
(*pskb)->csum = skb_checksum(*pskb, udphoff,
|
skb->csum = skb_checksum(skb, udphoff, skb->len - udphoff, 0);
|
||||||
(*pskb)->len - udphoff, 0);
|
|
||||||
udph->check = csum_tcpudp_magic(cp->vaddr, cp->caddr,
|
udph->check = csum_tcpudp_magic(cp->vaddr, cp->caddr,
|
||||||
(*pskb)->len - udphoff,
|
skb->len - udphoff,
|
||||||
cp->protocol,
|
cp->protocol, skb->csum);
|
||||||
(*pskb)->csum);
|
|
||||||
if (udph->check == 0)
|
if (udph->check == 0)
|
||||||
udph->check = CSUM_MANGLED_0;
|
udph->check = CSUM_MANGLED_0;
|
||||||
IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n",
|
IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n",
|
||||||
@ -183,30 +182,30 @@ udp_snat_handler(struct sk_buff **pskb,
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
udp_dnat_handler(struct sk_buff **pskb,
|
udp_dnat_handler(struct sk_buff *skb,
|
||||||
struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
|
struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
|
||||||
{
|
{
|
||||||
struct udphdr *udph;
|
struct udphdr *udph;
|
||||||
unsigned int udphoff = ip_hdrlen(*pskb);
|
unsigned int udphoff = ip_hdrlen(skb);
|
||||||
|
|
||||||
/* csum_check requires unshared skb */
|
/* csum_check requires unshared skb */
|
||||||
if (!ip_vs_make_skb_writable(pskb, udphoff+sizeof(*udph)))
|
if (!skb_make_writable(skb, udphoff+sizeof(*udph)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (unlikely(cp->app != NULL)) {
|
if (unlikely(cp->app != NULL)) {
|
||||||
/* Some checks before mangling */
|
/* Some checks before mangling */
|
||||||
if (pp->csum_check && !pp->csum_check(*pskb, pp))
|
if (pp->csum_check && !pp->csum_check(skb, pp))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attempt ip_vs_app call.
|
* Attempt ip_vs_app call.
|
||||||
* It will fix ip_vs_conn
|
* It will fix ip_vs_conn
|
||||||
*/
|
*/
|
||||||
if (!ip_vs_app_pkt_in(cp, pskb))
|
if (!ip_vs_app_pkt_in(cp, skb))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
udph = (void *)ip_hdr(*pskb) + udphoff;
|
udph = (void *)ip_hdr(skb) + udphoff;
|
||||||
udph->dest = cp->dport;
|
udph->dest = cp->dport;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -216,20 +215,18 @@ udp_dnat_handler(struct sk_buff **pskb,
|
|||||||
/* Only port and addr are changed, do fast csum update */
|
/* Only port and addr are changed, do fast csum update */
|
||||||
udp_fast_csum_update(udph, cp->vaddr, cp->daddr,
|
udp_fast_csum_update(udph, cp->vaddr, cp->daddr,
|
||||||
cp->vport, cp->dport);
|
cp->vport, cp->dport);
|
||||||
if ((*pskb)->ip_summed == CHECKSUM_COMPLETE)
|
if (skb->ip_summed == CHECKSUM_COMPLETE)
|
||||||
(*pskb)->ip_summed = CHECKSUM_NONE;
|
skb->ip_summed = CHECKSUM_NONE;
|
||||||
} else {
|
} else {
|
||||||
/* full checksum calculation */
|
/* full checksum calculation */
|
||||||
udph->check = 0;
|
udph->check = 0;
|
||||||
(*pskb)->csum = skb_checksum(*pskb, udphoff,
|
skb->csum = skb_checksum(skb, udphoff, skb->len - udphoff, 0);
|
||||||
(*pskb)->len - udphoff, 0);
|
|
||||||
udph->check = csum_tcpudp_magic(cp->caddr, cp->daddr,
|
udph->check = csum_tcpudp_magic(cp->caddr, cp->daddr,
|
||||||
(*pskb)->len - udphoff,
|
skb->len - udphoff,
|
||||||
cp->protocol,
|
cp->protocol, skb->csum);
|
||||||
(*pskb)->csum);
|
|
||||||
if (udph->check == 0)
|
if (udph->check == 0)
|
||||||
udph->check = CSUM_MANGLED_0;
|
udph->check = CSUM_MANGLED_0;
|
||||||
(*pskb)->ip_summed = CHECKSUM_UNNECESSARY;
|
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -253,7 +253,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* copy-on-write the packet before mangling it */
|
/* copy-on-write the packet before mangling it */
|
||||||
if (!ip_vs_make_skb_writable(&skb, sizeof(struct iphdr)))
|
if (!skb_make_writable(skb, sizeof(struct iphdr)))
|
||||||
goto tx_error_put;
|
goto tx_error_put;
|
||||||
|
|
||||||
if (skb_cow(skb, rt->u.dst.dev->hard_header_len))
|
if (skb_cow(skb, rt->u.dst.dev->hard_header_len))
|
||||||
@ -264,7 +264,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|||||||
skb->dst = &rt->u.dst;
|
skb->dst = &rt->u.dst;
|
||||||
|
|
||||||
/* mangle the packet */
|
/* mangle the packet */
|
||||||
if (pp->dnat_handler && !pp->dnat_handler(&skb, pp, cp))
|
if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp))
|
||||||
goto tx_error;
|
goto tx_error;
|
||||||
ip_hdr(skb)->daddr = cp->daddr;
|
ip_hdr(skb)->daddr = cp->daddr;
|
||||||
ip_send_check(ip_hdr(skb));
|
ip_send_check(ip_hdr(skb));
|
||||||
@ -529,7 +529,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* copy-on-write the packet before mangling it */
|
/* copy-on-write the packet before mangling it */
|
||||||
if (!ip_vs_make_skb_writable(&skb, offset))
|
if (!skb_make_writable(skb, offset))
|
||||||
goto tx_error_put;
|
goto tx_error_put;
|
||||||
|
|
||||||
if (skb_cow(skb, rt->u.dst.dev->hard_header_len))
|
if (skb_cow(skb, rt->u.dst.dev->hard_header_len))
|
||||||
|
@ -3,14 +3,15 @@
|
|||||||
#include <linux/netfilter.h>
|
#include <linux/netfilter.h>
|
||||||
#include <linux/netfilter_ipv4.h>
|
#include <linux/netfilter_ipv4.h>
|
||||||
#include <linux/ip.h>
|
#include <linux/ip.h>
|
||||||
|
#include <linux/skbuff.h>
|
||||||
#include <net/route.h>
|
#include <net/route.h>
|
||||||
#include <net/xfrm.h>
|
#include <net/xfrm.h>
|
||||||
#include <net/ip.h>
|
#include <net/ip.h>
|
||||||
|
|
||||||
/* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
|
/* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
|
||||||
int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type)
|
int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
|
||||||
{
|
{
|
||||||
const struct iphdr *iph = ip_hdr(*pskb);
|
const struct iphdr *iph = ip_hdr(skb);
|
||||||
struct rtable *rt;
|
struct rtable *rt;
|
||||||
struct flowi fl = {};
|
struct flowi fl = {};
|
||||||
struct dst_entry *odst;
|
struct dst_entry *odst;
|
||||||
@ -29,14 +30,14 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type)
|
|||||||
if (type == RTN_LOCAL)
|
if (type == RTN_LOCAL)
|
||||||
fl.nl_u.ip4_u.saddr = iph->saddr;
|
fl.nl_u.ip4_u.saddr = iph->saddr;
|
||||||
fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
|
fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
|
||||||
fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0;
|
fl.oif = skb->sk ? skb->sk->sk_bound_dev_if : 0;
|
||||||
fl.mark = (*pskb)->mark;
|
fl.mark = skb->mark;
|
||||||
if (ip_route_output_key(&rt, &fl) != 0)
|
if (ip_route_output_key(&rt, &fl) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Drop old route. */
|
/* Drop old route. */
|
||||||
dst_release((*pskb)->dst);
|
dst_release(skb->dst);
|
||||||
(*pskb)->dst = &rt->u.dst;
|
skb->dst = &rt->u.dst;
|
||||||
} else {
|
} else {
|
||||||
/* non-local src, find valid iif to satisfy
|
/* non-local src, find valid iif to satisfy
|
||||||
* rp-filter when calling ip_route_input. */
|
* rp-filter when calling ip_route_input. */
|
||||||
@ -44,8 +45,8 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type)
|
|||||||
if (ip_route_output_key(&rt, &fl) != 0)
|
if (ip_route_output_key(&rt, &fl) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
odst = (*pskb)->dst;
|
odst = skb->dst;
|
||||||
if (ip_route_input(*pskb, iph->daddr, iph->saddr,
|
if (ip_route_input(skb, iph->daddr, iph->saddr,
|
||||||
RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
|
RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
|
||||||
dst_release(&rt->u.dst);
|
dst_release(&rt->u.dst);
|
||||||
return -1;
|
return -1;
|
||||||
@ -54,70 +55,54 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type)
|
|||||||
dst_release(odst);
|
dst_release(odst);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*pskb)->dst->error)
|
if (skb->dst->error)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#ifdef CONFIG_XFRM
|
#ifdef CONFIG_XFRM
|
||||||
if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED) &&
|
if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
|
||||||
xfrm_decode_session(*pskb, &fl, AF_INET) == 0)
|
xfrm_decode_session(skb, &fl, AF_INET) == 0)
|
||||||
if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0))
|
if (xfrm_lookup(&skb->dst, &fl, skb->sk, 0))
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Change in oif may mean change in hh_len. */
|
/* Change in oif may mean change in hh_len. */
|
||||||
hh_len = (*pskb)->dst->dev->hard_header_len;
|
hh_len = skb->dst->dev->hard_header_len;
|
||||||
if (skb_headroom(*pskb) < hh_len) {
|
if (skb_headroom(skb) < hh_len &&
|
||||||
struct sk_buff *nskb;
|
pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC))
|
||||||
|
return -1;
|
||||||
nskb = skb_realloc_headroom(*pskb, hh_len);
|
|
||||||
if (!nskb)
|
|
||||||
return -1;
|
|
||||||
if ((*pskb)->sk)
|
|
||||||
skb_set_owner_w(nskb, (*pskb)->sk);
|
|
||||||
kfree_skb(*pskb);
|
|
||||||
*pskb = nskb;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ip_route_me_harder);
|
EXPORT_SYMBOL(ip_route_me_harder);
|
||||||
|
|
||||||
#ifdef CONFIG_XFRM
|
#ifdef CONFIG_XFRM
|
||||||
int ip_xfrm_me_harder(struct sk_buff **pskb)
|
int ip_xfrm_me_harder(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct flowi fl;
|
struct flowi fl;
|
||||||
unsigned int hh_len;
|
unsigned int hh_len;
|
||||||
struct dst_entry *dst;
|
struct dst_entry *dst;
|
||||||
|
|
||||||
if (IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)
|
if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
|
||||||
return 0;
|
return 0;
|
||||||
if (xfrm_decode_session(*pskb, &fl, AF_INET) < 0)
|
if (xfrm_decode_session(skb, &fl, AF_INET) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
dst = (*pskb)->dst;
|
dst = skb->dst;
|
||||||
if (dst->xfrm)
|
if (dst->xfrm)
|
||||||
dst = ((struct xfrm_dst *)dst)->route;
|
dst = ((struct xfrm_dst *)dst)->route;
|
||||||
dst_hold(dst);
|
dst_hold(dst);
|
||||||
|
|
||||||
if (xfrm_lookup(&dst, &fl, (*pskb)->sk, 0) < 0)
|
if (xfrm_lookup(&dst, &fl, skb->sk, 0) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
dst_release((*pskb)->dst);
|
dst_release(skb->dst);
|
||||||
(*pskb)->dst = dst;
|
skb->dst = dst;
|
||||||
|
|
||||||
/* Change in oif may mean change in hh_len. */
|
/* Change in oif may mean change in hh_len. */
|
||||||
hh_len = (*pskb)->dst->dev->hard_header_len;
|
hh_len = skb->dst->dev->hard_header_len;
|
||||||
if (skb_headroom(*pskb) < hh_len) {
|
if (skb_headroom(skb) < hh_len &&
|
||||||
struct sk_buff *nskb;
|
pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC))
|
||||||
|
return -1;
|
||||||
nskb = skb_realloc_headroom(*pskb, hh_len);
|
|
||||||
if (!nskb)
|
|
||||||
return -1;
|
|
||||||
if ((*pskb)->sk)
|
|
||||||
skb_set_owner_w(nskb, (*pskb)->sk);
|
|
||||||
kfree_skb(*pskb);
|
|
||||||
*pskb = nskb;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ip_xfrm_me_harder);
|
EXPORT_SYMBOL(ip_xfrm_me_harder);
|
||||||
@ -150,17 +135,17 @@ static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info)
|
static int nf_ip_reroute(struct sk_buff *skb, const struct nf_info *info)
|
||||||
{
|
{
|
||||||
const struct ip_rt_info *rt_info = nf_info_reroute(info);
|
const struct ip_rt_info *rt_info = nf_info_reroute(info);
|
||||||
|
|
||||||
if (info->hook == NF_IP_LOCAL_OUT) {
|
if (info->hook == NF_IP_LOCAL_OUT) {
|
||||||
const struct iphdr *iph = ip_hdr(*pskb);
|
const struct iphdr *iph = ip_hdr(skb);
|
||||||
|
|
||||||
if (!(iph->tos == rt_info->tos
|
if (!(iph->tos == rt_info->tos
|
||||||
&& iph->daddr == rt_info->daddr
|
&& iph->daddr == rt_info->daddr
|
||||||
&& iph->saddr == rt_info->saddr))
|
&& iph->saddr == rt_info->saddr))
|
||||||
return ip_route_me_harder(pskb, RTN_UNSPEC);
|
return ip_route_me_harder(skb, RTN_UNSPEC);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ static inline int arp_checkentry(const struct arpt_arp *arp)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int arpt_error(struct sk_buff **pskb,
|
static unsigned int arpt_error(struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
@ -215,7 +215,7 @@ static inline struct arpt_entry *get_entry(void *base, unsigned int offset)
|
|||||||
return (struct arpt_entry *)(base + offset);
|
return (struct arpt_entry *)(base + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int arpt_do_table(struct sk_buff **pskb,
|
unsigned int arpt_do_table(struct sk_buff *skb,
|
||||||
unsigned int hook,
|
unsigned int hook,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
@ -231,9 +231,9 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
|
|||||||
struct xt_table_info *private;
|
struct xt_table_info *private;
|
||||||
|
|
||||||
/* ARP header, plus 2 device addresses, plus 2 IP addresses. */
|
/* ARP header, plus 2 device addresses, plus 2 IP addresses. */
|
||||||
if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) +
|
if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
|
||||||
(2 * (*pskb)->dev->addr_len) +
|
(2 * skb->dev->addr_len) +
|
||||||
(2 * sizeof(u32)))))
|
(2 * sizeof(u32)))))
|
||||||
return NF_DROP;
|
return NF_DROP;
|
||||||
|
|
||||||
indev = in ? in->name : nulldevname;
|
indev = in ? in->name : nulldevname;
|
||||||
@ -245,14 +245,14 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
|
|||||||
e = get_entry(table_base, private->hook_entry[hook]);
|
e = get_entry(table_base, private->hook_entry[hook]);
|
||||||
back = get_entry(table_base, private->underflow[hook]);
|
back = get_entry(table_base, private->underflow[hook]);
|
||||||
|
|
||||||
arp = arp_hdr(*pskb);
|
arp = arp_hdr(skb);
|
||||||
do {
|
do {
|
||||||
if (arp_packet_match(arp, (*pskb)->dev, indev, outdev, &e->arp)) {
|
if (arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) {
|
||||||
struct arpt_entry_target *t;
|
struct arpt_entry_target *t;
|
||||||
int hdr_len;
|
int hdr_len;
|
||||||
|
|
||||||
hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) +
|
hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) +
|
||||||
(2 * (*pskb)->dev->addr_len);
|
(2 * skb->dev->addr_len);
|
||||||
ADD_COUNTER(e->counters, hdr_len, 1);
|
ADD_COUNTER(e->counters, hdr_len, 1);
|
||||||
|
|
||||||
t = arpt_get_target(e);
|
t = arpt_get_target(e);
|
||||||
@ -290,14 +290,14 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
|
|||||||
/* Targets which reenter must return
|
/* Targets which reenter must return
|
||||||
* abs. verdicts
|
* abs. verdicts
|
||||||
*/
|
*/
|
||||||
verdict = t->u.kernel.target->target(pskb,
|
verdict = t->u.kernel.target->target(skb,
|
||||||
in, out,
|
in, out,
|
||||||
hook,
|
hook,
|
||||||
t->u.kernel.target,
|
t->u.kernel.target,
|
||||||
t->data);
|
t->data);
|
||||||
|
|
||||||
/* Target might have changed stuff. */
|
/* Target might have changed stuff. */
|
||||||
arp = arp_hdr(*pskb);
|
arp = arp_hdr(skb);
|
||||||
|
|
||||||
if (verdict == ARPT_CONTINUE)
|
if (verdict == ARPT_CONTINUE)
|
||||||
e = (void *)e + e->next_offset;
|
e = (void *)e + e->next_offset;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* module that allows mangling of the arp payload */
|
/* module that allows mangling of the arp payload */
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/netfilter.h>
|
||||||
#include <linux/netfilter_arp/arpt_mangle.h>
|
#include <linux/netfilter_arp/arpt_mangle.h>
|
||||||
#include <net/sock.h>
|
#include <net/sock.h>
|
||||||
|
|
||||||
@ -8,7 +9,7 @@ MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
|
|||||||
MODULE_DESCRIPTION("arptables arp payload mangle target");
|
MODULE_DESCRIPTION("arptables arp payload mangle target");
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
target(struct sk_buff **pskb,
|
target(struct sk_buff *skb,
|
||||||
const struct net_device *in, const struct net_device *out,
|
const struct net_device *in, const struct net_device *out,
|
||||||
unsigned int hooknum, const struct xt_target *target,
|
unsigned int hooknum, const struct xt_target *target,
|
||||||
const void *targinfo)
|
const void *targinfo)
|
||||||
@ -18,47 +19,38 @@ target(struct sk_buff **pskb,
|
|||||||
unsigned char *arpptr;
|
unsigned char *arpptr;
|
||||||
int pln, hln;
|
int pln, hln;
|
||||||
|
|
||||||
if (skb_shared(*pskb) || skb_cloned(*pskb)) {
|
if (skb_make_writable(skb, skb->len))
|
||||||
struct sk_buff *nskb;
|
return NF_DROP;
|
||||||
|
|
||||||
nskb = skb_copy(*pskb, GFP_ATOMIC);
|
arp = arp_hdr(skb);
|
||||||
if (!nskb)
|
arpptr = skb_network_header(skb) + sizeof(*arp);
|
||||||
return NF_DROP;
|
|
||||||
if ((*pskb)->sk)
|
|
||||||
skb_set_owner_w(nskb, (*pskb)->sk);
|
|
||||||
kfree_skb(*pskb);
|
|
||||||
*pskb = nskb;
|
|
||||||
}
|
|
||||||
|
|
||||||
arp = arp_hdr(*pskb);
|
|
||||||
arpptr = skb_network_header(*pskb) + sizeof(*arp);
|
|
||||||
pln = arp->ar_pln;
|
pln = arp->ar_pln;
|
||||||
hln = arp->ar_hln;
|
hln = arp->ar_hln;
|
||||||
/* We assume that pln and hln were checked in the match */
|
/* We assume that pln and hln were checked in the match */
|
||||||
if (mangle->flags & ARPT_MANGLE_SDEV) {
|
if (mangle->flags & ARPT_MANGLE_SDEV) {
|
||||||
if (ARPT_DEV_ADDR_LEN_MAX < hln ||
|
if (ARPT_DEV_ADDR_LEN_MAX < hln ||
|
||||||
(arpptr + hln > skb_tail_pointer(*pskb)))
|
(arpptr + hln > skb_tail_pointer(skb)))
|
||||||
return NF_DROP;
|
return NF_DROP;
|
||||||
memcpy(arpptr, mangle->src_devaddr, hln);
|
memcpy(arpptr, mangle->src_devaddr, hln);
|
||||||
}
|
}
|
||||||
arpptr += hln;
|
arpptr += hln;
|
||||||
if (mangle->flags & ARPT_MANGLE_SIP) {
|
if (mangle->flags & ARPT_MANGLE_SIP) {
|
||||||
if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
|
if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
|
||||||
(arpptr + pln > skb_tail_pointer(*pskb)))
|
(arpptr + pln > skb_tail_pointer(skb)))
|
||||||
return NF_DROP;
|
return NF_DROP;
|
||||||
memcpy(arpptr, &mangle->u_s.src_ip, pln);
|
memcpy(arpptr, &mangle->u_s.src_ip, pln);
|
||||||
}
|
}
|
||||||
arpptr += pln;
|
arpptr += pln;
|
||||||
if (mangle->flags & ARPT_MANGLE_TDEV) {
|
if (mangle->flags & ARPT_MANGLE_TDEV) {
|
||||||
if (ARPT_DEV_ADDR_LEN_MAX < hln ||
|
if (ARPT_DEV_ADDR_LEN_MAX < hln ||
|
||||||
(arpptr + hln > skb_tail_pointer(*pskb)))
|
(arpptr + hln > skb_tail_pointer(skb)))
|
||||||
return NF_DROP;
|
return NF_DROP;
|
||||||
memcpy(arpptr, mangle->tgt_devaddr, hln);
|
memcpy(arpptr, mangle->tgt_devaddr, hln);
|
||||||
}
|
}
|
||||||
arpptr += hln;
|
arpptr += hln;
|
||||||
if (mangle->flags & ARPT_MANGLE_TIP) {
|
if (mangle->flags & ARPT_MANGLE_TIP) {
|
||||||
if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
|
if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
|
||||||
(arpptr + pln > skb_tail_pointer(*pskb)))
|
(arpptr + pln > skb_tail_pointer(skb)))
|
||||||
return NF_DROP;
|
return NF_DROP;
|
||||||
memcpy(arpptr, &mangle->u_t.tgt_ip, pln);
|
memcpy(arpptr, &mangle->u_t.tgt_ip, pln);
|
||||||
}
|
}
|
||||||
|
@ -56,12 +56,12 @@ static struct arpt_table packet_filter = {
|
|||||||
|
|
||||||
/* The work comes in here from netfilter.c */
|
/* The work comes in here from netfilter.c */
|
||||||
static unsigned int arpt_hook(unsigned int hook,
|
static unsigned int arpt_hook(unsigned int hook,
|
||||||
struct sk_buff **pskb,
|
struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
return arpt_do_table(pskb, hook, in, out, &packet_filter);
|
return arpt_do_table(skb, hook, in, out, &packet_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct nf_hook_ops arpt_ops[] = {
|
static struct nf_hook_ops arpt_ops[] = {
|
||||||
|
@ -335,6 +335,7 @@ static int
|
|||||||
ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
|
ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
|
||||||
{
|
{
|
||||||
int diff;
|
int diff;
|
||||||
|
int err;
|
||||||
struct iphdr *user_iph = (struct iphdr *)v->payload;
|
struct iphdr *user_iph = (struct iphdr *)v->payload;
|
||||||
|
|
||||||
if (v->data_len < sizeof(*user_iph))
|
if (v->data_len < sizeof(*user_iph))
|
||||||
@ -347,25 +348,18 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
|
|||||||
if (v->data_len > 0xFFFF)
|
if (v->data_len > 0xFFFF)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (diff > skb_tailroom(e->skb)) {
|
if (diff > skb_tailroom(e->skb)) {
|
||||||
struct sk_buff *newskb;
|
err = pskb_expand_head(e->skb, 0,
|
||||||
|
diff - skb_tailroom(e->skb),
|
||||||
newskb = skb_copy_expand(e->skb,
|
GFP_ATOMIC);
|
||||||
skb_headroom(e->skb),
|
if (err) {
|
||||||
diff,
|
printk(KERN_WARNING "ip_queue: error "
|
||||||
GFP_ATOMIC);
|
"in mangle, dropping packet: %d\n", -err);
|
||||||
if (newskb == NULL) {
|
return err;
|
||||||
printk(KERN_WARNING "ip_queue: OOM "
|
|
||||||
"in mangle, dropping packet\n");
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
}
|
||||||
if (e->skb->sk)
|
|
||||||
skb_set_owner_w(newskb, e->skb->sk);
|
|
||||||
kfree_skb(e->skb);
|
|
||||||
e->skb = newskb;
|
|
||||||
}
|
}
|
||||||
skb_put(e->skb, diff);
|
skb_put(e->skb, diff);
|
||||||
}
|
}
|
||||||
if (!skb_make_writable(&e->skb, v->data_len))
|
if (!skb_make_writable(e->skb, v->data_len))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
skb_copy_to_linear_data(e->skb, v->payload, v->data_len);
|
skb_copy_to_linear_data(e->skb, v->payload, v->data_len);
|
||||||
e->skb->ip_summed = CHECKSUM_NONE;
|
e->skb->ip_summed = CHECKSUM_NONE;
|
||||||
|
@ -169,7 +169,7 @@ ip_checkentry(const struct ipt_ip *ip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
ipt_error(struct sk_buff **pskb,
|
ipt_error(struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
@ -312,7 +312,7 @@ static void trace_packet(struct sk_buff *skb,
|
|||||||
|
|
||||||
/* Returns one of the generic firewall policies, like NF_ACCEPT. */
|
/* Returns one of the generic firewall policies, like NF_ACCEPT. */
|
||||||
unsigned int
|
unsigned int
|
||||||
ipt_do_table(struct sk_buff **pskb,
|
ipt_do_table(struct sk_buff *skb,
|
||||||
unsigned int hook,
|
unsigned int hook,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
@ -331,8 +331,8 @@ ipt_do_table(struct sk_buff **pskb,
|
|||||||
struct xt_table_info *private;
|
struct xt_table_info *private;
|
||||||
|
|
||||||
/* Initialization */
|
/* Initialization */
|
||||||
ip = ip_hdr(*pskb);
|
ip = ip_hdr(skb);
|
||||||
datalen = (*pskb)->len - ip->ihl * 4;
|
datalen = skb->len - ip->ihl * 4;
|
||||||
indev = in ? in->name : nulldevname;
|
indev = in ? in->name : nulldevname;
|
||||||
outdev = out ? out->name : nulldevname;
|
outdev = out ? out->name : nulldevname;
|
||||||
/* We handle fragments by dealing with the first fragment as
|
/* We handle fragments by dealing with the first fragment as
|
||||||
@ -359,7 +359,7 @@ ipt_do_table(struct sk_buff **pskb,
|
|||||||
struct ipt_entry_target *t;
|
struct ipt_entry_target *t;
|
||||||
|
|
||||||
if (IPT_MATCH_ITERATE(e, do_match,
|
if (IPT_MATCH_ITERATE(e, do_match,
|
||||||
*pskb, in, out,
|
skb, in, out,
|
||||||
offset, &hotdrop) != 0)
|
offset, &hotdrop) != 0)
|
||||||
goto no_match;
|
goto no_match;
|
||||||
|
|
||||||
@ -371,8 +371,8 @@ ipt_do_table(struct sk_buff **pskb,
|
|||||||
#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
|
#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
|
||||||
defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
|
defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
|
||||||
/* The packet is traced: log it */
|
/* The packet is traced: log it */
|
||||||
if (unlikely((*pskb)->nf_trace))
|
if (unlikely(skb->nf_trace))
|
||||||
trace_packet(*pskb, hook, in, out,
|
trace_packet(skb, hook, in, out,
|
||||||
table->name, private, e);
|
table->name, private, e);
|
||||||
#endif
|
#endif
|
||||||
/* Standard target? */
|
/* Standard target? */
|
||||||
@ -410,7 +410,7 @@ ipt_do_table(struct sk_buff **pskb,
|
|||||||
((struct ipt_entry *)table_base)->comefrom
|
((struct ipt_entry *)table_base)->comefrom
|
||||||
= 0xeeeeeeec;
|
= 0xeeeeeeec;
|
||||||
#endif
|
#endif
|
||||||
verdict = t->u.kernel.target->target(pskb,
|
verdict = t->u.kernel.target->target(skb,
|
||||||
in, out,
|
in, out,
|
||||||
hook,
|
hook,
|
||||||
t->u.kernel.target,
|
t->u.kernel.target,
|
||||||
@ -428,8 +428,8 @@ ipt_do_table(struct sk_buff **pskb,
|
|||||||
= 0x57acc001;
|
= 0x57acc001;
|
||||||
#endif
|
#endif
|
||||||
/* Target might have changed stuff. */
|
/* Target might have changed stuff. */
|
||||||
ip = ip_hdr(*pskb);
|
ip = ip_hdr(skb);
|
||||||
datalen = (*pskb)->len - ip->ihl * 4;
|
datalen = skb->len - ip->ihl * 4;
|
||||||
|
|
||||||
if (verdict == IPT_CONTINUE)
|
if (verdict == IPT_CONTINUE)
|
||||||
e = (void *)e + e->next_offset;
|
e = (void *)e + e->next_offset;
|
||||||
|
@ -289,7 +289,7 @@ clusterip_responsible(const struct clusterip_config *config, u_int32_t hash)
|
|||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
target(struct sk_buff **pskb,
|
target(struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
@ -305,7 +305,7 @@ target(struct sk_buff **pskb,
|
|||||||
* is only decremented by destroy() - and ip_tables guarantees
|
* is only decremented by destroy() - and ip_tables guarantees
|
||||||
* that the ->target() function isn't called after ->destroy() */
|
* that the ->target() function isn't called after ->destroy() */
|
||||||
|
|
||||||
ct = nf_ct_get(*pskb, &ctinfo);
|
ct = nf_ct_get(skb, &ctinfo);
|
||||||
if (ct == NULL) {
|
if (ct == NULL) {
|
||||||
printk(KERN_ERR "CLUSTERIP: no conntrack!\n");
|
printk(KERN_ERR "CLUSTERIP: no conntrack!\n");
|
||||||
/* FIXME: need to drop invalid ones, since replies
|
/* FIXME: need to drop invalid ones, since replies
|
||||||
@ -316,7 +316,7 @@ target(struct sk_buff **pskb,
|
|||||||
|
|
||||||
/* special case: ICMP error handling. conntrack distinguishes between
|
/* special case: ICMP error handling. conntrack distinguishes between
|
||||||
* error messages (RELATED) and information requests (see below) */
|
* error messages (RELATED) and information requests (see below) */
|
||||||
if (ip_hdr(*pskb)->protocol == IPPROTO_ICMP
|
if (ip_hdr(skb)->protocol == IPPROTO_ICMP
|
||||||
&& (ctinfo == IP_CT_RELATED
|
&& (ctinfo == IP_CT_RELATED
|
||||||
|| ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY))
|
|| ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY))
|
||||||
return XT_CONTINUE;
|
return XT_CONTINUE;
|
||||||
@ -325,7 +325,7 @@ target(struct sk_buff **pskb,
|
|||||||
* TIMESTAMP, INFO_REQUEST or ADDRESS type icmp packets from here
|
* TIMESTAMP, INFO_REQUEST or ADDRESS type icmp packets from here
|
||||||
* on, which all have an ID field [relevant for hashing]. */
|
* on, which all have an ID field [relevant for hashing]. */
|
||||||
|
|
||||||
hash = clusterip_hashfn(*pskb, cipinfo->config);
|
hash = clusterip_hashfn(skb, cipinfo->config);
|
||||||
|
|
||||||
switch (ctinfo) {
|
switch (ctinfo) {
|
||||||
case IP_CT_NEW:
|
case IP_CT_NEW:
|
||||||
@ -355,7 +355,7 @@ target(struct sk_buff **pskb,
|
|||||||
|
|
||||||
/* despite being received via linklayer multicast, this is
|
/* despite being received via linklayer multicast, this is
|
||||||
* actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */
|
* actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */
|
||||||
(*pskb)->pkt_type = PACKET_HOST;
|
skb->pkt_type = PACKET_HOST;
|
||||||
|
|
||||||
return XT_CONTINUE;
|
return XT_CONTINUE;
|
||||||
}
|
}
|
||||||
@ -505,12 +505,12 @@ static void arp_print(struct arp_payload *payload)
|
|||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
arp_mangle(unsigned int hook,
|
arp_mangle(unsigned int hook,
|
||||||
struct sk_buff **pskb,
|
struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
struct arphdr *arp = arp_hdr(*pskb);
|
struct arphdr *arp = arp_hdr(skb);
|
||||||
struct arp_payload *payload;
|
struct arp_payload *payload;
|
||||||
struct clusterip_config *c;
|
struct clusterip_config *c;
|
||||||
|
|
||||||
|
@ -26,15 +26,15 @@ MODULE_DESCRIPTION("iptables ECN modification module");
|
|||||||
/* set ECT codepoint from IP header.
|
/* set ECT codepoint from IP header.
|
||||||
* return false if there was an error. */
|
* return false if there was an error. */
|
||||||
static inline bool
|
static inline bool
|
||||||
set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
|
set_ect_ip(struct sk_buff *skb, const struct ipt_ECN_info *einfo)
|
||||||
{
|
{
|
||||||
struct iphdr *iph = ip_hdr(*pskb);
|
struct iphdr *iph = ip_hdr(skb);
|
||||||
|
|
||||||
if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
|
if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
|
||||||
__u8 oldtos;
|
__u8 oldtos;
|
||||||
if (!skb_make_writable(pskb, sizeof(struct iphdr)))
|
if (!skb_make_writable(skb, sizeof(struct iphdr)))
|
||||||
return false;
|
return false;
|
||||||
iph = ip_hdr(*pskb);
|
iph = ip_hdr(skb);
|
||||||
oldtos = iph->tos;
|
oldtos = iph->tos;
|
||||||
iph->tos &= ~IPT_ECN_IP_MASK;
|
iph->tos &= ~IPT_ECN_IP_MASK;
|
||||||
iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
|
iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
|
||||||
@ -45,14 +45,13 @@ set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
|
|||||||
|
|
||||||
/* Return false if there was an error. */
|
/* Return false if there was an error. */
|
||||||
static inline bool
|
static inline bool
|
||||||
set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
|
set_ect_tcp(struct sk_buff *skb, const struct ipt_ECN_info *einfo)
|
||||||
{
|
{
|
||||||
struct tcphdr _tcph, *tcph;
|
struct tcphdr _tcph, *tcph;
|
||||||
__be16 oldval;
|
__be16 oldval;
|
||||||
|
|
||||||
/* Not enought header? */
|
/* Not enought header? */
|
||||||
tcph = skb_header_pointer(*pskb, ip_hdrlen(*pskb),
|
tcph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph);
|
||||||
sizeof(_tcph), &_tcph);
|
|
||||||
if (!tcph)
|
if (!tcph)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -62,9 +61,9 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
|
|||||||
tcph->cwr == einfo->proto.tcp.cwr))
|
tcph->cwr == einfo->proto.tcp.cwr))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph)))
|
if (!skb_make_writable(skb, ip_hdrlen(skb) + sizeof(*tcph)))
|
||||||
return false;
|
return false;
|
||||||
tcph = (void *)ip_hdr(*pskb) + ip_hdrlen(*pskb);
|
tcph = (void *)ip_hdr(skb) + ip_hdrlen(skb);
|
||||||
|
|
||||||
oldval = ((__be16 *)tcph)[6];
|
oldval = ((__be16 *)tcph)[6];
|
||||||
if (einfo->operation & IPT_ECN_OP_SET_ECE)
|
if (einfo->operation & IPT_ECN_OP_SET_ECE)
|
||||||
@ -72,13 +71,13 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
|
|||||||
if (einfo->operation & IPT_ECN_OP_SET_CWR)
|
if (einfo->operation & IPT_ECN_OP_SET_CWR)
|
||||||
tcph->cwr = einfo->proto.tcp.cwr;
|
tcph->cwr = einfo->proto.tcp.cwr;
|
||||||
|
|
||||||
nf_proto_csum_replace2(&tcph->check, *pskb,
|
nf_proto_csum_replace2(&tcph->check, skb,
|
||||||
oldval, ((__be16 *)tcph)[6], 0);
|
oldval, ((__be16 *)tcph)[6], 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
target(struct sk_buff **pskb,
|
target(struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
@ -88,12 +87,12 @@ target(struct sk_buff **pskb,
|
|||||||
const struct ipt_ECN_info *einfo = targinfo;
|
const struct ipt_ECN_info *einfo = targinfo;
|
||||||
|
|
||||||
if (einfo->operation & IPT_ECN_OP_SET_IP)
|
if (einfo->operation & IPT_ECN_OP_SET_IP)
|
||||||
if (!set_ect_ip(pskb, einfo))
|
if (!set_ect_ip(skb, einfo))
|
||||||
return NF_DROP;
|
return NF_DROP;
|
||||||
|
|
||||||
if (einfo->operation & (IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR)
|
if (einfo->operation & (IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR)
|
||||||
&& ip_hdr(*pskb)->protocol == IPPROTO_TCP)
|
&& ip_hdr(skb)->protocol == IPPROTO_TCP)
|
||||||
if (!set_ect_tcp(pskb, einfo))
|
if (!set_ect_tcp(skb, einfo))
|
||||||
return NF_DROP;
|
return NF_DROP;
|
||||||
|
|
||||||
return XT_CONTINUE;
|
return XT_CONTINUE;
|
||||||
|
@ -418,7 +418,7 @@ ipt_log_packet(unsigned int pf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
ipt_log_target(struct sk_buff **pskb,
|
ipt_log_target(struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
@ -432,7 +432,7 @@ ipt_log_target(struct sk_buff **pskb,
|
|||||||
li.u.log.level = loginfo->level;
|
li.u.log.level = loginfo->level;
|
||||||
li.u.log.logflags = loginfo->logflags;
|
li.u.log.logflags = loginfo->logflags;
|
||||||
|
|
||||||
ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
|
ipt_log_packet(PF_INET, hooknum, skb, in, out, &li,
|
||||||
loginfo->prefix);
|
loginfo->prefix);
|
||||||
return XT_CONTINUE;
|
return XT_CONTINUE;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ masquerade_check(const char *tablename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
masquerade_target(struct sk_buff **pskb,
|
masquerade_target(struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
@ -69,7 +69,7 @@ masquerade_target(struct sk_buff **pskb,
|
|||||||
|
|
||||||
NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING);
|
NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING);
|
||||||
|
|
||||||
ct = nf_ct_get(*pskb, &ctinfo);
|
ct = nf_ct_get(skb, &ctinfo);
|
||||||
nat = nfct_nat(ct);
|
nat = nfct_nat(ct);
|
||||||
|
|
||||||
NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
|
NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
|
||||||
@ -82,7 +82,7 @@ masquerade_target(struct sk_buff **pskb,
|
|||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
|
|
||||||
mr = targinfo;
|
mr = targinfo;
|
||||||
rt = (struct rtable *)(*pskb)->dst;
|
rt = (struct rtable *)skb->dst;
|
||||||
newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE);
|
newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE);
|
||||||
if (!newsrc) {
|
if (!newsrc) {
|
||||||
printk("MASQUERADE: %s ate my IP address\n", out->name);
|
printk("MASQUERADE: %s ate my IP address\n", out->name);
|
||||||
|
@ -43,7 +43,7 @@ check(const char *tablename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
target(struct sk_buff **pskb,
|
target(struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
@ -59,14 +59,14 @@ target(struct sk_buff **pskb,
|
|||||||
NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING
|
NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING
|
||||||
|| hooknum == NF_IP_POST_ROUTING
|
|| hooknum == NF_IP_POST_ROUTING
|
||||||
|| hooknum == NF_IP_LOCAL_OUT);
|
|| hooknum == NF_IP_LOCAL_OUT);
|
||||||
ct = nf_ct_get(*pskb, &ctinfo);
|
ct = nf_ct_get(skb, &ctinfo);
|
||||||
|
|
||||||
netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip);
|
netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip);
|
||||||
|
|
||||||
if (hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT)
|
if (hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT)
|
||||||
new_ip = ip_hdr(*pskb)->daddr & ~netmask;
|
new_ip = ip_hdr(skb)->daddr & ~netmask;
|
||||||
else
|
else
|
||||||
new_ip = ip_hdr(*pskb)->saddr & ~netmask;
|
new_ip = ip_hdr(skb)->saddr & ~netmask;
|
||||||
new_ip |= mr->range[0].min_ip & netmask;
|
new_ip |= mr->range[0].min_ip & netmask;
|
||||||
|
|
||||||
newrange = ((struct nf_nat_range)
|
newrange = ((struct nf_nat_range)
|
||||||
|
@ -47,7 +47,7 @@ redirect_check(const char *tablename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
redirect_target(struct sk_buff **pskb,
|
redirect_target(struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
@ -63,7 +63,7 @@ redirect_target(struct sk_buff **pskb,
|
|||||||
NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING
|
NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING
|
||||||
|| hooknum == NF_IP_LOCAL_OUT);
|
|| hooknum == NF_IP_LOCAL_OUT);
|
||||||
|
|
||||||
ct = nf_ct_get(*pskb, &ctinfo);
|
ct = nf_ct_get(skb, &ctinfo);
|
||||||
NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
|
NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
|
||||||
|
|
||||||
/* Local packets: make them go to loopback */
|
/* Local packets: make them go to loopback */
|
||||||
@ -76,7 +76,7 @@ redirect_target(struct sk_buff **pskb,
|
|||||||
newdst = 0;
|
newdst = 0;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
indev = __in_dev_get_rcu((*pskb)->dev);
|
indev = __in_dev_get_rcu(skb->dev);
|
||||||
if (indev && (ifa = indev->ifa_list))
|
if (indev && (ifa = indev->ifa_list))
|
||||||
newdst = ifa->ifa_local;
|
newdst = ifa->ifa_local;
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
@ -131,7 +131,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
|
|||||||
)
|
)
|
||||||
addr_type = RTN_LOCAL;
|
addr_type = RTN_LOCAL;
|
||||||
|
|
||||||
if (ip_route_me_harder(&nskb, addr_type))
|
if (ip_route_me_harder(nskb, addr_type))
|
||||||
goto free_nskb;
|
goto free_nskb;
|
||||||
|
|
||||||
nskb->ip_summed = CHECKSUM_NONE;
|
nskb->ip_summed = CHECKSUM_NONE;
|
||||||
@ -162,7 +162,7 @@ static inline void send_unreach(struct sk_buff *skb_in, int code)
|
|||||||
icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
|
icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int reject(struct sk_buff **pskb,
|
static unsigned int reject(struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
@ -173,7 +173,7 @@ static unsigned int reject(struct sk_buff **pskb,
|
|||||||
|
|
||||||
/* Our naive response construction doesn't deal with IP
|
/* Our naive response construction doesn't deal with IP
|
||||||
options, and probably shouldn't try. */
|
options, and probably shouldn't try. */
|
||||||
if (ip_hdrlen(*pskb) != sizeof(struct iphdr))
|
if (ip_hdrlen(skb) != sizeof(struct iphdr))
|
||||||
return NF_DROP;
|
return NF_DROP;
|
||||||
|
|
||||||
/* WARNING: This code causes reentry within iptables.
|
/* WARNING: This code causes reentry within iptables.
|
||||||
@ -181,28 +181,28 @@ static unsigned int reject(struct sk_buff **pskb,
|
|||||||
must return an absolute verdict. --RR */
|
must return an absolute verdict. --RR */
|
||||||
switch (reject->with) {
|
switch (reject->with) {
|
||||||
case IPT_ICMP_NET_UNREACHABLE:
|
case IPT_ICMP_NET_UNREACHABLE:
|
||||||
send_unreach(*pskb, ICMP_NET_UNREACH);
|
send_unreach(skb, ICMP_NET_UNREACH);
|
||||||
break;
|
break;
|
||||||
case IPT_ICMP_HOST_UNREACHABLE:
|
case IPT_ICMP_HOST_UNREACHABLE:
|
||||||
send_unreach(*pskb, ICMP_HOST_UNREACH);
|
send_unreach(skb, ICMP_HOST_UNREACH);
|
||||||
break;
|
break;
|
||||||
case IPT_ICMP_PROT_UNREACHABLE:
|
case IPT_ICMP_PROT_UNREACHABLE:
|
||||||
send_unreach(*pskb, ICMP_PROT_UNREACH);
|
send_unreach(skb, ICMP_PROT_UNREACH);
|
||||||
break;
|
break;
|
||||||
case IPT_ICMP_PORT_UNREACHABLE:
|
case IPT_ICMP_PORT_UNREACHABLE:
|
||||||
send_unreach(*pskb, ICMP_PORT_UNREACH);
|
send_unreach(skb, ICMP_PORT_UNREACH);
|
||||||
break;
|
break;
|
||||||
case IPT_ICMP_NET_PROHIBITED:
|
case IPT_ICMP_NET_PROHIBITED:
|
||||||
send_unreach(*pskb, ICMP_NET_ANO);
|
send_unreach(skb, ICMP_NET_ANO);
|
||||||
break;
|
break;
|
||||||
case IPT_ICMP_HOST_PROHIBITED:
|
case IPT_ICMP_HOST_PROHIBITED:
|
||||||
send_unreach(*pskb, ICMP_HOST_ANO);
|
send_unreach(skb, ICMP_HOST_ANO);
|
||||||
break;
|
break;
|
||||||
case IPT_ICMP_ADMIN_PROHIBITED:
|
case IPT_ICMP_ADMIN_PROHIBITED:
|
||||||
send_unreach(*pskb, ICMP_PKT_FILTERED);
|
send_unreach(skb, ICMP_PKT_FILTERED);
|
||||||
break;
|
break;
|
||||||
case IPT_TCP_RESET:
|
case IPT_TCP_RESET:
|
||||||
send_reset(*pskb, hooknum);
|
send_reset(skb, hooknum);
|
||||||
case IPT_ICMP_ECHOREPLY:
|
case IPT_ICMP_ECHOREPLY:
|
||||||
/* Doesn't happen. */
|
/* Doesn't happen. */
|
||||||
break;
|
break;
|
||||||
|
@ -104,7 +104,7 @@ same_destroy(const struct xt_target *target, void *targinfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
same_target(struct sk_buff **pskb,
|
same_target(struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
@ -121,7 +121,7 @@ same_target(struct sk_buff **pskb,
|
|||||||
|
|
||||||
NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
|
NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
|
||||||
hooknum == NF_IP_POST_ROUTING);
|
hooknum == NF_IP_POST_ROUTING);
|
||||||
ct = nf_ct_get(*pskb, &ctinfo);
|
ct = nf_ct_get(skb, &ctinfo);
|
||||||
|
|
||||||
t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
|
t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
|
|||||||
MODULE_DESCRIPTION("iptables TOS mangling module");
|
MODULE_DESCRIPTION("iptables TOS mangling module");
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
target(struct sk_buff **pskb,
|
target(struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
@ -29,13 +29,13 @@ target(struct sk_buff **pskb,
|
|||||||
const void *targinfo)
|
const void *targinfo)
|
||||||
{
|
{
|
||||||
const struct ipt_tos_target_info *tosinfo = targinfo;
|
const struct ipt_tos_target_info *tosinfo = targinfo;
|
||||||
struct iphdr *iph = ip_hdr(*pskb);
|
struct iphdr *iph = ip_hdr(skb);
|
||||||
|
|
||||||
if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) {
|
if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) {
|
||||||
__u8 oldtos;
|
__u8 oldtos;
|
||||||
if (!skb_make_writable(pskb, sizeof(struct iphdr)))
|
if (!skb_make_writable(skb, sizeof(struct iphdr)))
|
||||||
return NF_DROP;
|
return NF_DROP;
|
||||||
iph = ip_hdr(*pskb);
|
iph = ip_hdr(skb);
|
||||||
oldtos = iph->tos;
|
oldtos = iph->tos;
|
||||||
iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos;
|
iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos;
|
||||||
nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
|
nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
|
||||||
|
@ -20,7 +20,7 @@ MODULE_DESCRIPTION("IP tables TTL modification module");
|
|||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
ipt_ttl_target(struct sk_buff **pskb,
|
ipt_ttl_target(struct sk_buff *skb,
|
||||||
const struct net_device *in, const struct net_device *out,
|
const struct net_device *in, const struct net_device *out,
|
||||||
unsigned int hooknum, const struct xt_target *target,
|
unsigned int hooknum, const struct xt_target *target,
|
||||||
const void *targinfo)
|
const void *targinfo)
|
||||||
@ -29,10 +29,10 @@ ipt_ttl_target(struct sk_buff **pskb,
|
|||||||
const struct ipt_TTL_info *info = targinfo;
|
const struct ipt_TTL_info *info = targinfo;
|
||||||
int new_ttl;
|
int new_ttl;
|
||||||
|
|
||||||
if (!skb_make_writable(pskb, (*pskb)->len))
|
if (!skb_make_writable(skb, skb->len))
|
||||||
return NF_DROP;
|
return NF_DROP;
|
||||||
|
|
||||||
iph = ip_hdr(*pskb);
|
iph = ip_hdr(skb);
|
||||||
|
|
||||||
switch (info->mode) {
|
switch (info->mode) {
|
||||||
case IPT_TTL_SET:
|
case IPT_TTL_SET:
|
||||||
|
@ -279,7 +279,7 @@ alloc_failure:
|
|||||||
spin_unlock_bh(&ulog_lock);
|
spin_unlock_bh(&ulog_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int ipt_ulog_target(struct sk_buff **pskb,
|
static unsigned int ipt_ulog_target(struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
@ -288,7 +288,7 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb,
|
|||||||
{
|
{
|
||||||
struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
|
struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
|
||||||
|
|
||||||
ipt_ulog_packet(hooknum, *pskb, in, out, loginfo, NULL);
|
ipt_ulog_packet(hooknum, skb, in, out, loginfo, NULL);
|
||||||
|
|
||||||
return XT_CONTINUE;
|
return XT_CONTINUE;
|
||||||
}
|
}
|
||||||
|
@ -62,31 +62,31 @@ static struct xt_table packet_filter = {
|
|||||||
/* The work comes in here from netfilter.c. */
|
/* The work comes in here from netfilter.c. */
|
||||||
static unsigned int
|
static unsigned int
|
||||||
ipt_hook(unsigned int hook,
|
ipt_hook(unsigned int hook,
|
||||||
struct sk_buff **pskb,
|
struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
return ipt_do_table(pskb, hook, in, out, &packet_filter);
|
return ipt_do_table(skb, hook, in, out, &packet_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
ipt_local_out_hook(unsigned int hook,
|
ipt_local_out_hook(unsigned int hook,
|
||||||
struct sk_buff **pskb,
|
struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
/* root is playing with raw sockets. */
|
/* root is playing with raw sockets. */
|
||||||
if ((*pskb)->len < sizeof(struct iphdr)
|
if (skb->len < sizeof(struct iphdr) ||
|
||||||
|| ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
|
ip_hdrlen(skb) < sizeof(struct iphdr)) {
|
||||||
if (net_ratelimit())
|
if (net_ratelimit())
|
||||||
printk("iptable_filter: ignoring short SOCK_RAW "
|
printk("iptable_filter: ignoring short SOCK_RAW "
|
||||||
"packet.\n");
|
"packet.\n");
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ipt_do_table(pskb, hook, in, out, &packet_filter);
|
return ipt_do_table(skb, hook, in, out, &packet_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct nf_hook_ops ipt_ops[] = {
|
static struct nf_hook_ops ipt_ops[] = {
|
||||||
|
@ -75,17 +75,17 @@ static struct xt_table packet_mangler = {
|
|||||||
/* The work comes in here from netfilter.c. */
|
/* The work comes in here from netfilter.c. */
|
||||||
static unsigned int
|
static unsigned int
|
||||||
ipt_route_hook(unsigned int hook,
|
ipt_route_hook(unsigned int hook,
|
||||||
struct sk_buff **pskb,
|
struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
return ipt_do_table(pskb, hook, in, out, &packet_mangler);
|
return ipt_do_table(skb, hook, in, out, &packet_mangler);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
ipt_local_hook(unsigned int hook,
|
ipt_local_hook(unsigned int hook,
|
||||||
struct sk_buff **pskb,
|
struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
@ -97,8 +97,8 @@ ipt_local_hook(unsigned int hook,
|
|||||||
u_int32_t mark;
|
u_int32_t mark;
|
||||||
|
|
||||||
/* root is playing with raw sockets. */
|
/* root is playing with raw sockets. */
|
||||||
if ((*pskb)->len < sizeof(struct iphdr)
|
if (skb->len < sizeof(struct iphdr)
|
||||||
|| ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
|
|| ip_hdrlen(skb) < sizeof(struct iphdr)) {
|
||||||
if (net_ratelimit())
|
if (net_ratelimit())
|
||||||
printk("iptable_mangle: ignoring short SOCK_RAW "
|
printk("iptable_mangle: ignoring short SOCK_RAW "
|
||||||
"packet.\n");
|
"packet.\n");
|
||||||
@ -106,22 +106,22 @@ ipt_local_hook(unsigned int hook,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Save things which could affect route */
|
/* Save things which could affect route */
|
||||||
mark = (*pskb)->mark;
|
mark = skb->mark;
|
||||||
iph = ip_hdr(*pskb);
|
iph = ip_hdr(skb);
|
||||||
saddr = iph->saddr;
|
saddr = iph->saddr;
|
||||||
daddr = iph->daddr;
|
daddr = iph->daddr;
|
||||||
tos = iph->tos;
|
tos = iph->tos;
|
||||||
|
|
||||||
ret = ipt_do_table(pskb, hook, in, out, &packet_mangler);
|
ret = ipt_do_table(skb, hook, in, out, &packet_mangler);
|
||||||
/* Reroute for ANY change. */
|
/* Reroute for ANY change. */
|
||||||
if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) {
|
if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) {
|
||||||
iph = ip_hdr(*pskb);
|
iph = ip_hdr(skb);
|
||||||
|
|
||||||
if (iph->saddr != saddr ||
|
if (iph->saddr != saddr ||
|
||||||
iph->daddr != daddr ||
|
iph->daddr != daddr ||
|
||||||
(*pskb)->mark != mark ||
|
skb->mark != mark ||
|
||||||
iph->tos != tos)
|
iph->tos != tos)
|
||||||
if (ip_route_me_harder(pskb, RTN_UNSPEC))
|
if (ip_route_me_harder(skb, RTN_UNSPEC))
|
||||||
ret = NF_DROP;
|
ret = NF_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,30 +47,30 @@ static struct xt_table packet_raw = {
|
|||||||
/* The work comes in here from netfilter.c. */
|
/* The work comes in here from netfilter.c. */
|
||||||
static unsigned int
|
static unsigned int
|
||||||
ipt_hook(unsigned int hook,
|
ipt_hook(unsigned int hook,
|
||||||
struct sk_buff **pskb,
|
struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
return ipt_do_table(pskb, hook, in, out, &packet_raw);
|
return ipt_do_table(skb, hook, in, out, &packet_raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
ipt_local_hook(unsigned int hook,
|
ipt_local_hook(unsigned int hook,
|
||||||
struct sk_buff **pskb,
|
struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
/* root is playing with raw sockets. */
|
/* root is playing with raw sockets. */
|
||||||
if ((*pskb)->len < sizeof(struct iphdr) ||
|
if (skb->len < sizeof(struct iphdr) ||
|
||||||
ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
|
ip_hdrlen(skb) < sizeof(struct iphdr)) {
|
||||||
if (net_ratelimit())
|
if (net_ratelimit())
|
||||||
printk("iptable_raw: ignoring short SOCK_RAW"
|
printk("iptable_raw: ignoring short SOCK_RAW"
|
||||||
"packet.\n");
|
"packet.\n");
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
}
|
}
|
||||||
return ipt_do_table(pskb, hook, in, out, &packet_raw);
|
return ipt_do_table(skb, hook, in, out, &packet_raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 'raw' is the very first table. */
|
/* 'raw' is the very first table. */
|
||||||
|
@ -63,19 +63,20 @@ static int ipv4_print_conntrack(struct seq_file *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Returns new sk_buff, or NULL */
|
/* Returns new sk_buff, or NULL */
|
||||||
static struct sk_buff *
|
static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
|
||||||
nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
|
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
skb_orphan(skb);
|
skb_orphan(skb);
|
||||||
|
|
||||||
local_bh_disable();
|
local_bh_disable();
|
||||||
skb = ip_defrag(skb, user);
|
err = ip_defrag(skb, user);
|
||||||
local_bh_enable();
|
local_bh_enable();
|
||||||
|
|
||||||
if (skb)
|
if (!err)
|
||||||
ip_send_check(ip_hdr(skb));
|
ip_send_check(ip_hdr(skb));
|
||||||
|
|
||||||
return skb;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
|
static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
|
||||||
@ -99,17 +100,17 @@ static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int ipv4_confirm(unsigned int hooknum,
|
static unsigned int ipv4_confirm(unsigned int hooknum,
|
||||||
struct sk_buff **pskb,
|
struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
/* We've seen it coming out the other side: confirm it */
|
/* We've seen it coming out the other side: confirm it */
|
||||||
return nf_conntrack_confirm(pskb);
|
return nf_conntrack_confirm(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int ipv4_conntrack_help(unsigned int hooknum,
|
static unsigned int ipv4_conntrack_help(unsigned int hooknum,
|
||||||
struct sk_buff **pskb,
|
struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
@ -120,7 +121,7 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum,
|
|||||||
struct nf_conntrack_helper *helper;
|
struct nf_conntrack_helper *helper;
|
||||||
|
|
||||||
/* This is where we call the helper: as the packet goes out. */
|
/* This is where we call the helper: as the packet goes out. */
|
||||||
ct = nf_ct_get(*pskb, &ctinfo);
|
ct = nf_ct_get(skb, &ctinfo);
|
||||||
if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
|
if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
|
|
||||||
@ -131,56 +132,55 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum,
|
|||||||
helper = rcu_dereference(help->helper);
|
helper = rcu_dereference(help->helper);
|
||||||
if (!helper)
|
if (!helper)
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
return helper->help(pskb, skb_network_offset(*pskb) + ip_hdrlen(*pskb),
|
return helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb),
|
||||||
ct, ctinfo);
|
ct, ctinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
|
static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
|
||||||
struct sk_buff **pskb,
|
struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
/* Previously seen (loopback)? Ignore. Do this before
|
/* Previously seen (loopback)? Ignore. Do this before
|
||||||
fragment check. */
|
fragment check. */
|
||||||
if ((*pskb)->nfct)
|
if (skb->nfct)
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
|
|
||||||
/* Gather fragments. */
|
/* Gather fragments. */
|
||||||
if (ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)) {
|
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
|
||||||
*pskb = nf_ct_ipv4_gather_frags(*pskb,
|
if (nf_ct_ipv4_gather_frags(skb,
|
||||||
hooknum == NF_IP_PRE_ROUTING ?
|
hooknum == NF_IP_PRE_ROUTING ?
|
||||||
IP_DEFRAG_CONNTRACK_IN :
|
IP_DEFRAG_CONNTRACK_IN :
|
||||||
IP_DEFRAG_CONNTRACK_OUT);
|
IP_DEFRAG_CONNTRACK_OUT))
|
||||||
if (!*pskb)
|
|
||||||
return NF_STOLEN;
|
return NF_STOLEN;
|
||||||
}
|
}
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int ipv4_conntrack_in(unsigned int hooknum,
|
static unsigned int ipv4_conntrack_in(unsigned int hooknum,
|
||||||
struct sk_buff **pskb,
|
struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
return nf_conntrack_in(PF_INET, hooknum, pskb);
|
return nf_conntrack_in(PF_INET, hooknum, skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int ipv4_conntrack_local(unsigned int hooknum,
|
static unsigned int ipv4_conntrack_local(unsigned int hooknum,
|
||||||
struct sk_buff **pskb,
|
struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
int (*okfn)(struct sk_buff *))
|
int (*okfn)(struct sk_buff *))
|
||||||
{
|
{
|
||||||
/* root is playing with raw sockets. */
|
/* root is playing with raw sockets. */
|
||||||
if ((*pskb)->len < sizeof(struct iphdr)
|
if (skb->len < sizeof(struct iphdr) ||
|
||||||
|| ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
|
ip_hdrlen(skb) < sizeof(struct iphdr)) {
|
||||||
if (net_ratelimit())
|
if (net_ratelimit())
|
||||||
printk("ipt_hook: happy cracking.\n");
|
printk("ipt_hook: happy cracking.\n");
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
}
|
}
|
||||||
return nf_conntrack_in(PF_INET, hooknum, pskb);
|
return nf_conntrack_in(PF_INET, hooknum, skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connection tracking may drop packets, but never alters them, so
|
/* Connection tracking may drop packets, but never alters them, so
|
||||||
|
@ -24,7 +24,7 @@ MODULE_DESCRIPTION("Amanda NAT helper");
|
|||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_ALIAS("ip_nat_amanda");
|
MODULE_ALIAS("ip_nat_amanda");
|
||||||
|
|
||||||
static unsigned int help(struct sk_buff **pskb,
|
static unsigned int help(struct sk_buff *skb,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned int matchoff,
|
unsigned int matchoff,
|
||||||
unsigned int matchlen,
|
unsigned int matchlen,
|
||||||
@ -53,7 +53,7 @@ static unsigned int help(struct sk_buff **pskb,
|
|||||||
return NF_DROP;
|
return NF_DROP;
|
||||||
|
|
||||||
sprintf(buffer, "%u", port);
|
sprintf(buffer, "%u", port);
|
||||||
ret = nf_nat_mangle_udp_packet(pskb, exp->master, ctinfo,
|
ret = nf_nat_mangle_udp_packet(skb, exp->master, ctinfo,
|
||||||
matchoff, matchlen,
|
matchoff, matchlen,
|
||||||
buffer, strlen(buffer));
|
buffer, strlen(buffer));
|
||||||
if (ret != NF_ACCEPT)
|
if (ret != NF_ACCEPT)
|
||||||
|
@ -349,7 +349,7 @@ EXPORT_SYMBOL(nf_nat_setup_info);
|
|||||||
/* Returns true if succeeded. */
|
/* Returns true if succeeded. */
|
||||||
static int
|
static int
|
||||||
manip_pkt(u_int16_t proto,
|
manip_pkt(u_int16_t proto,
|
||||||
struct sk_buff **pskb,
|
struct sk_buff *skb,
|
||||||
unsigned int iphdroff,
|
unsigned int iphdroff,
|
||||||
const struct nf_conntrack_tuple *target,
|
const struct nf_conntrack_tuple *target,
|
||||||
enum nf_nat_manip_type maniptype)
|
enum nf_nat_manip_type maniptype)
|
||||||
@ -357,19 +357,19 @@ manip_pkt(u_int16_t proto,
|
|||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
struct nf_nat_protocol *p;
|
struct nf_nat_protocol *p;
|
||||||
|
|
||||||
if (!skb_make_writable(pskb, iphdroff + sizeof(*iph)))
|
if (!skb_make_writable(skb, iphdroff + sizeof(*iph)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
iph = (void *)(*pskb)->data + iphdroff;
|
iph = (void *)skb->data + iphdroff;
|
||||||
|
|
||||||
/* Manipulate protcol part. */
|
/* Manipulate protcol part. */
|
||||||
|
|
||||||
/* rcu_read_lock()ed by nf_hook_slow */
|
/* rcu_read_lock()ed by nf_hook_slow */
|
||||||
p = __nf_nat_proto_find(proto);
|
p = __nf_nat_proto_find(proto);
|
||||||
if (!p->manip_pkt(pskb, iphdroff, target, maniptype))
|
if (!p->manip_pkt(skb, iphdroff, target, maniptype))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
iph = (void *)(*pskb)->data + iphdroff;
|
iph = (void *)skb->data + iphdroff;
|
||||||
|
|
||||||
if (maniptype == IP_NAT_MANIP_SRC) {
|
if (maniptype == IP_NAT_MANIP_SRC) {
|
||||||
nf_csum_replace4(&iph->check, iph->saddr, target->src.u3.ip);
|
nf_csum_replace4(&iph->check, iph->saddr, target->src.u3.ip);
|
||||||
@ -385,7 +385,7 @@ manip_pkt(u_int16_t proto,
|
|||||||
unsigned int nf_nat_packet(struct nf_conn *ct,
|
unsigned int nf_nat_packet(struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
struct sk_buff **pskb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
|
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
|
||||||
unsigned long statusbit;
|
unsigned long statusbit;
|
||||||
@ -407,7 +407,7 @@ unsigned int nf_nat_packet(struct nf_conn *ct,
|
|||||||
/* We are aiming to look like inverse of other direction. */
|
/* We are aiming to look like inverse of other direction. */
|
||||||
nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
|
nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
|
||||||
|
|
||||||
if (!manip_pkt(target.dst.protonum, pskb, 0, &target, mtype))
|
if (!manip_pkt(target.dst.protonum, skb, 0, &target, mtype))
|
||||||
return NF_DROP;
|
return NF_DROP;
|
||||||
}
|
}
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
@ -418,7 +418,7 @@ EXPORT_SYMBOL_GPL(nf_nat_packet);
|
|||||||
int nf_nat_icmp_reply_translation(struct nf_conn *ct,
|
int nf_nat_icmp_reply_translation(struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
struct sk_buff **pskb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
struct icmphdr icmp;
|
struct icmphdr icmp;
|
||||||
@ -426,24 +426,24 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
|
|||||||
} *inside;
|
} *inside;
|
||||||
struct nf_conntrack_l4proto *l4proto;
|
struct nf_conntrack_l4proto *l4proto;
|
||||||
struct nf_conntrack_tuple inner, target;
|
struct nf_conntrack_tuple inner, target;
|
||||||
int hdrlen = ip_hdrlen(*pskb);
|
int hdrlen = ip_hdrlen(skb);
|
||||||
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
|
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
|
||||||
unsigned long statusbit;
|
unsigned long statusbit;
|
||||||
enum nf_nat_manip_type manip = HOOK2MANIP(hooknum);
|
enum nf_nat_manip_type manip = HOOK2MANIP(hooknum);
|
||||||
|
|
||||||
if (!skb_make_writable(pskb, hdrlen + sizeof(*inside)))
|
if (!skb_make_writable(skb, hdrlen + sizeof(*inside)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
inside = (void *)(*pskb)->data + ip_hdrlen(*pskb);
|
inside = (void *)skb->data + ip_hdrlen(skb);
|
||||||
|
|
||||||
/* We're actually going to mangle it beyond trivial checksum
|
/* We're actually going to mangle it beyond trivial checksum
|
||||||
adjustment, so make sure the current checksum is correct. */
|
adjustment, so make sure the current checksum is correct. */
|
||||||
if (nf_ip_checksum(*pskb, hooknum, hdrlen, 0))
|
if (nf_ip_checksum(skb, hooknum, hdrlen, 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Must be RELATED */
|
/* Must be RELATED */
|
||||||
NF_CT_ASSERT((*pskb)->nfctinfo == IP_CT_RELATED ||
|
NF_CT_ASSERT(skb->nfctinfo == IP_CT_RELATED ||
|
||||||
(*pskb)->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY);
|
skb->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY);
|
||||||
|
|
||||||
/* Redirects on non-null nats must be dropped, else they'll
|
/* Redirects on non-null nats must be dropped, else they'll
|
||||||
start talking to each other without our translation, and be
|
start talking to each other without our translation, and be
|
||||||
@ -458,15 +458,15 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pr_debug("icmp_reply_translation: translating error %p manip %u "
|
pr_debug("icmp_reply_translation: translating error %p manip %u "
|
||||||
"dir %s\n", *pskb, manip,
|
"dir %s\n", skb, manip,
|
||||||
dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
|
dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
|
||||||
|
|
||||||
/* rcu_read_lock()ed by nf_hook_slow */
|
/* rcu_read_lock()ed by nf_hook_slow */
|
||||||
l4proto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol);
|
l4proto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol);
|
||||||
|
|
||||||
if (!nf_ct_get_tuple(*pskb,
|
if (!nf_ct_get_tuple(skb,
|
||||||
ip_hdrlen(*pskb) + sizeof(struct icmphdr),
|
ip_hdrlen(skb) + sizeof(struct icmphdr),
|
||||||
(ip_hdrlen(*pskb) +
|
(ip_hdrlen(skb) +
|
||||||
sizeof(struct icmphdr) + inside->ip.ihl * 4),
|
sizeof(struct icmphdr) + inside->ip.ihl * 4),
|
||||||
(u_int16_t)AF_INET,
|
(u_int16_t)AF_INET,
|
||||||
inside->ip.protocol,
|
inside->ip.protocol,
|
||||||
@ -478,19 +478,19 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
|
|||||||
pass all hooks (locally-generated ICMP). Consider incoming
|
pass all hooks (locally-generated ICMP). Consider incoming
|
||||||
packet: PREROUTING (DST manip), routing produces ICMP, goes
|
packet: PREROUTING (DST manip), routing produces ICMP, goes
|
||||||
through POSTROUTING (which must correct the DST manip). */
|
through POSTROUTING (which must correct the DST manip). */
|
||||||
if (!manip_pkt(inside->ip.protocol, pskb,
|
if (!manip_pkt(inside->ip.protocol, skb,
|
||||||
ip_hdrlen(*pskb) + sizeof(inside->icmp),
|
ip_hdrlen(skb) + sizeof(inside->icmp),
|
||||||
&ct->tuplehash[!dir].tuple,
|
&ct->tuplehash[!dir].tuple,
|
||||||
!manip))
|
!manip))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
|
if (skb->ip_summed != CHECKSUM_PARTIAL) {
|
||||||
/* Reloading "inside" here since manip_pkt inner. */
|
/* Reloading "inside" here since manip_pkt inner. */
|
||||||
inside = (void *)(*pskb)->data + ip_hdrlen(*pskb);
|
inside = (void *)skb->data + ip_hdrlen(skb);
|
||||||
inside->icmp.checksum = 0;
|
inside->icmp.checksum = 0;
|
||||||
inside->icmp.checksum =
|
inside->icmp.checksum =
|
||||||
csum_fold(skb_checksum(*pskb, hdrlen,
|
csum_fold(skb_checksum(skb, hdrlen,
|
||||||
(*pskb)->len - hdrlen, 0));
|
skb->len - hdrlen, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change outer to look the reply to an incoming packet
|
/* Change outer to look the reply to an incoming packet
|
||||||
@ -506,7 +506,7 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
|
|||||||
|
|
||||||
if (ct->status & statusbit) {
|
if (ct->status & statusbit) {
|
||||||
nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
|
nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
|
||||||
if (!manip_pkt(0, pskb, 0, &target, manip))
|
if (!manip_pkt(0, skb, 0, &target, manip))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ MODULE_ALIAS("ip_nat_ftp");
|
|||||||
/* FIXME: Time out? --RR */
|
/* FIXME: Time out? --RR */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mangle_rfc959_packet(struct sk_buff **pskb,
|
mangle_rfc959_packet(struct sk_buff *skb,
|
||||||
__be32 newip,
|
__be32 newip,
|
||||||
u_int16_t port,
|
u_int16_t port,
|
||||||
unsigned int matchoff,
|
unsigned int matchoff,
|
||||||
@ -43,13 +43,13 @@ mangle_rfc959_packet(struct sk_buff **pskb,
|
|||||||
|
|
||||||
pr_debug("calling nf_nat_mangle_tcp_packet\n");
|
pr_debug("calling nf_nat_mangle_tcp_packet\n");
|
||||||
|
|
||||||
return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
|
return nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff,
|
||||||
matchlen, buffer, strlen(buffer));
|
matchlen, buffer, strlen(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* |1|132.235.1.2|6275| */
|
/* |1|132.235.1.2|6275| */
|
||||||
static int
|
static int
|
||||||
mangle_eprt_packet(struct sk_buff **pskb,
|
mangle_eprt_packet(struct sk_buff *skb,
|
||||||
__be32 newip,
|
__be32 newip,
|
||||||
u_int16_t port,
|
u_int16_t port,
|
||||||
unsigned int matchoff,
|
unsigned int matchoff,
|
||||||
@ -63,13 +63,13 @@ mangle_eprt_packet(struct sk_buff **pskb,
|
|||||||
|
|
||||||
pr_debug("calling nf_nat_mangle_tcp_packet\n");
|
pr_debug("calling nf_nat_mangle_tcp_packet\n");
|
||||||
|
|
||||||
return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
|
return nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff,
|
||||||
matchlen, buffer, strlen(buffer));
|
matchlen, buffer, strlen(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* |1|132.235.1.2|6275| */
|
/* |1|132.235.1.2|6275| */
|
||||||
static int
|
static int
|
||||||
mangle_epsv_packet(struct sk_buff **pskb,
|
mangle_epsv_packet(struct sk_buff *skb,
|
||||||
__be32 newip,
|
__be32 newip,
|
||||||
u_int16_t port,
|
u_int16_t port,
|
||||||
unsigned int matchoff,
|
unsigned int matchoff,
|
||||||
@ -83,11 +83,11 @@ mangle_epsv_packet(struct sk_buff **pskb,
|
|||||||
|
|
||||||
pr_debug("calling nf_nat_mangle_tcp_packet\n");
|
pr_debug("calling nf_nat_mangle_tcp_packet\n");
|
||||||
|
|
||||||
return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
|
return nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff,
|
||||||
matchlen, buffer, strlen(buffer));
|
matchlen, buffer, strlen(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int (*mangle[])(struct sk_buff **, __be32, u_int16_t,
|
static int (*mangle[])(struct sk_buff *, __be32, u_int16_t,
|
||||||
unsigned int, unsigned int, struct nf_conn *,
|
unsigned int, unsigned int, struct nf_conn *,
|
||||||
enum ip_conntrack_info)
|
enum ip_conntrack_info)
|
||||||
= {
|
= {
|
||||||
@ -99,7 +99,7 @@ static int (*mangle[])(struct sk_buff **, __be32, u_int16_t,
|
|||||||
|
|
||||||
/* So, this packet has hit the connection tracking matching code.
|
/* So, this packet has hit the connection tracking matching code.
|
||||||
Mangle it, and change the expectation to match the new version. */
|
Mangle it, and change the expectation to match the new version. */
|
||||||
static unsigned int nf_nat_ftp(struct sk_buff **pskb,
|
static unsigned int nf_nat_ftp(struct sk_buff *skb,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
enum nf_ct_ftp_type type,
|
enum nf_ct_ftp_type type,
|
||||||
unsigned int matchoff,
|
unsigned int matchoff,
|
||||||
@ -132,7 +132,7 @@ static unsigned int nf_nat_ftp(struct sk_buff **pskb,
|
|||||||
if (port == 0)
|
if (port == 0)
|
||||||
return NF_DROP;
|
return NF_DROP;
|
||||||
|
|
||||||
if (!mangle[type](pskb, newip, port, matchoff, matchlen, ct, ctinfo)) {
|
if (!mangle[type](skb, newip, port, matchoff, matchlen, ct, ctinfo)) {
|
||||||
nf_ct_unexpect_related(exp);
|
nf_ct_unexpect_related(exp);
|
||||||
return NF_DROP;
|
return NF_DROP;
|
||||||
}
|
}
|
||||||
|
@ -22,12 +22,12 @@
|
|||||||
#include <linux/netfilter/nf_conntrack_h323.h>
|
#include <linux/netfilter/nf_conntrack_h323.h>
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
static int set_addr(struct sk_buff **pskb,
|
static int set_addr(struct sk_buff *skb,
|
||||||
unsigned char **data, int dataoff,
|
unsigned char **data, int dataoff,
|
||||||
unsigned int addroff, __be32 ip, __be16 port)
|
unsigned int addroff, __be32 ip, __be16 port)
|
||||||
{
|
{
|
||||||
enum ip_conntrack_info ctinfo;
|
enum ip_conntrack_info ctinfo;
|
||||||
struct nf_conn *ct = nf_ct_get(*pskb, &ctinfo);
|
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
|
||||||
struct {
|
struct {
|
||||||
__be32 ip;
|
__be32 ip;
|
||||||
__be16 port;
|
__be16 port;
|
||||||
@ -38,8 +38,8 @@ static int set_addr(struct sk_buff **pskb,
|
|||||||
buf.port = port;
|
buf.port = port;
|
||||||
addroff += dataoff;
|
addroff += dataoff;
|
||||||
|
|
||||||
if (ip_hdr(*pskb)->protocol == IPPROTO_TCP) {
|
if (ip_hdr(skb)->protocol == IPPROTO_TCP) {
|
||||||
if (!nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
|
if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
|
||||||
addroff, sizeof(buf),
|
addroff, sizeof(buf),
|
||||||
(char *) &buf, sizeof(buf))) {
|
(char *) &buf, sizeof(buf))) {
|
||||||
if (net_ratelimit())
|
if (net_ratelimit())
|
||||||
@ -49,14 +49,13 @@ static int set_addr(struct sk_buff **pskb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Relocate data pointer */
|
/* Relocate data pointer */
|
||||||
th = skb_header_pointer(*pskb, ip_hdrlen(*pskb),
|
th = skb_header_pointer(skb, ip_hdrlen(skb),
|
||||||
sizeof(_tcph), &_tcph);
|
sizeof(_tcph), &_tcph);
|
||||||
if (th == NULL)
|
if (th == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
*data = (*pskb)->data + ip_hdrlen(*pskb) +
|
*data = skb->data + ip_hdrlen(skb) + th->doff * 4 + dataoff;
|
||||||
th->doff * 4 + dataoff;
|
|
||||||
} else {
|
} else {
|
||||||
if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
|
if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
|
||||||
addroff, sizeof(buf),
|
addroff, sizeof(buf),
|
||||||
(char *) &buf, sizeof(buf))) {
|
(char *) &buf, sizeof(buf))) {
|
||||||
if (net_ratelimit())
|
if (net_ratelimit())
|
||||||
@ -67,36 +66,35 @@ static int set_addr(struct sk_buff **pskb,
|
|||||||
/* nf_nat_mangle_udp_packet uses skb_make_writable() to copy
|
/* nf_nat_mangle_udp_packet uses skb_make_writable() to copy
|
||||||
* or pull everything in a linear buffer, so we can safely
|
* or pull everything in a linear buffer, so we can safely
|
||||||
* use the skb pointers now */
|
* use the skb pointers now */
|
||||||
*data = ((*pskb)->data + ip_hdrlen(*pskb) +
|
*data = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);
|
||||||
sizeof(struct udphdr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
static int set_h225_addr(struct sk_buff **pskb,
|
static int set_h225_addr(struct sk_buff *skb,
|
||||||
unsigned char **data, int dataoff,
|
unsigned char **data, int dataoff,
|
||||||
TransportAddress *taddr,
|
TransportAddress *taddr,
|
||||||
union nf_conntrack_address *addr, __be16 port)
|
union nf_conntrack_address *addr, __be16 port)
|
||||||
{
|
{
|
||||||
return set_addr(pskb, data, dataoff, taddr->ipAddress.ip,
|
return set_addr(skb, data, dataoff, taddr->ipAddress.ip,
|
||||||
addr->ip, port);
|
addr->ip, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
static int set_h245_addr(struct sk_buff **pskb,
|
static int set_h245_addr(struct sk_buff *skb,
|
||||||
unsigned char **data, int dataoff,
|
unsigned char **data, int dataoff,
|
||||||
H245_TransportAddress *taddr,
|
H245_TransportAddress *taddr,
|
||||||
union nf_conntrack_address *addr, __be16 port)
|
union nf_conntrack_address *addr, __be16 port)
|
||||||
{
|
{
|
||||||
return set_addr(pskb, data, dataoff,
|
return set_addr(skb, data, dataoff,
|
||||||
taddr->unicastAddress.iPAddress.network,
|
taddr->unicastAddress.iPAddress.network,
|
||||||
addr->ip, port);
|
addr->ip, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct,
|
static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned char **data,
|
unsigned char **data,
|
||||||
TransportAddress *taddr, int count)
|
TransportAddress *taddr, int count)
|
||||||
@ -125,7 +123,7 @@ static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct,
|
|||||||
NIPQUAD(addr.ip), port,
|
NIPQUAD(addr.ip), port,
|
||||||
NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
|
NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
|
||||||
info->sig_port[!dir]);
|
info->sig_port[!dir]);
|
||||||
return set_h225_addr(pskb, data, 0, &taddr[i],
|
return set_h225_addr(skb, data, 0, &taddr[i],
|
||||||
&ct->tuplehash[!dir].
|
&ct->tuplehash[!dir].
|
||||||
tuple.dst.u3,
|
tuple.dst.u3,
|
||||||
info->sig_port[!dir]);
|
info->sig_port[!dir]);
|
||||||
@ -137,7 +135,7 @@ static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct,
|
|||||||
NIPQUAD(addr.ip), port,
|
NIPQUAD(addr.ip), port,
|
||||||
NIPQUAD(ct->tuplehash[!dir].tuple.src.u3.ip),
|
NIPQUAD(ct->tuplehash[!dir].tuple.src.u3.ip),
|
||||||
info->sig_port[!dir]);
|
info->sig_port[!dir]);
|
||||||
return set_h225_addr(pskb, data, 0, &taddr[i],
|
return set_h225_addr(skb, data, 0, &taddr[i],
|
||||||
&ct->tuplehash[!dir].
|
&ct->tuplehash[!dir].
|
||||||
tuple.src.u3,
|
tuple.src.u3,
|
||||||
info->sig_port[!dir]);
|
info->sig_port[!dir]);
|
||||||
@ -149,7 +147,7 @@ static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct,
|
static int set_ras_addr(struct sk_buff *skb, struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned char **data,
|
unsigned char **data,
|
||||||
TransportAddress *taddr, int count)
|
TransportAddress *taddr, int count)
|
||||||
@ -168,7 +166,7 @@ static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct,
|
|||||||
NIPQUAD(addr.ip), ntohs(port),
|
NIPQUAD(addr.ip), ntohs(port),
|
||||||
NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
|
NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
|
||||||
ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port));
|
ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port));
|
||||||
return set_h225_addr(pskb, data, 0, &taddr[i],
|
return set_h225_addr(skb, data, 0, &taddr[i],
|
||||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||||
ct->tuplehash[!dir].tuple.
|
ct->tuplehash[!dir].tuple.
|
||||||
dst.u.udp.port);
|
dst.u.udp.port);
|
||||||
@ -179,7 +177,7 @@ static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
|
static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned char **data, int dataoff,
|
unsigned char **data, int dataoff,
|
||||||
H245_TransportAddress *taddr,
|
H245_TransportAddress *taddr,
|
||||||
@ -244,7 +242,7 @@ static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Modify signal */
|
/* Modify signal */
|
||||||
if (set_h245_addr(pskb, data, dataoff, taddr,
|
if (set_h245_addr(skb, data, dataoff, taddr,
|
||||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||||
htons((port & htons(1)) ? nated_port + 1 :
|
htons((port & htons(1)) ? nated_port + 1 :
|
||||||
nated_port)) == 0) {
|
nated_port)) == 0) {
|
||||||
@ -273,7 +271,7 @@ static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct,
|
static int nat_t120(struct sk_buff *skb, struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned char **data, int dataoff,
|
unsigned char **data, int dataoff,
|
||||||
H245_TransportAddress *taddr, __be16 port,
|
H245_TransportAddress *taddr, __be16 port,
|
||||||
@ -301,7 +299,7 @@ static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Modify signal */
|
/* Modify signal */
|
||||||
if (set_h245_addr(pskb, data, dataoff, taddr,
|
if (set_h245_addr(skb, data, dataoff, taddr,
|
||||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||||
htons(nated_port)) < 0) {
|
htons(nated_port)) < 0) {
|
||||||
nf_ct_unexpect_related(exp);
|
nf_ct_unexpect_related(exp);
|
||||||
@ -318,7 +316,7 @@ static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct,
|
static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned char **data, int dataoff,
|
unsigned char **data, int dataoff,
|
||||||
TransportAddress *taddr, __be16 port,
|
TransportAddress *taddr, __be16 port,
|
||||||
@ -351,7 +349,7 @@ static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Modify signal */
|
/* Modify signal */
|
||||||
if (set_h225_addr(pskb, data, dataoff, taddr,
|
if (set_h225_addr(skb, data, dataoff, taddr,
|
||||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||||
htons(nated_port)) == 0) {
|
htons(nated_port)) == 0) {
|
||||||
/* Save ports */
|
/* Save ports */
|
||||||
@ -406,7 +404,7 @@ static void ip_nat_q931_expect(struct nf_conn *new,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct,
|
static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned char **data, TransportAddress *taddr, int idx,
|
unsigned char **data, TransportAddress *taddr, int idx,
|
||||||
__be16 port, struct nf_conntrack_expect *exp)
|
__be16 port, struct nf_conntrack_expect *exp)
|
||||||
@ -439,7 +437,7 @@ static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Modify signal */
|
/* Modify signal */
|
||||||
if (set_h225_addr(pskb, data, 0, &taddr[idx],
|
if (set_h225_addr(skb, data, 0, &taddr[idx],
|
||||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||||
htons(nated_port)) == 0) {
|
htons(nated_port)) == 0) {
|
||||||
/* Save ports */
|
/* Save ports */
|
||||||
@ -450,7 +448,7 @@ static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct,
|
|||||||
if (idx > 0 &&
|
if (idx > 0 &&
|
||||||
get_h225_addr(ct, *data, &taddr[0], &addr, &port) &&
|
get_h225_addr(ct, *data, &taddr[0], &addr, &port) &&
|
||||||
(ntohl(addr.ip) & 0xff000000) == 0x7f000000) {
|
(ntohl(addr.ip) & 0xff000000) == 0x7f000000) {
|
||||||
set_h225_addr(pskb, data, 0, &taddr[0],
|
set_h225_addr(skb, data, 0, &taddr[0],
|
||||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||||
info->sig_port[!dir]);
|
info->sig_port[!dir]);
|
||||||
}
|
}
|
||||||
@ -495,7 +493,7 @@ static void ip_nat_callforwarding_expect(struct nf_conn *new,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct,
|
static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned char **data, int dataoff,
|
unsigned char **data, int dataoff,
|
||||||
TransportAddress *taddr, __be16 port,
|
TransportAddress *taddr, __be16 port,
|
||||||
@ -525,7 +523,7 @@ static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Modify signal */
|
/* Modify signal */
|
||||||
if (!set_h225_addr(pskb, data, dataoff, taddr,
|
if (!set_h225_addr(skb, data, dataoff, taddr,
|
||||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||||
htons(nated_port)) == 0) {
|
htons(nated_port)) == 0) {
|
||||||
nf_ct_unexpect_related(exp);
|
nf_ct_unexpect_related(exp);
|
||||||
|
@ -111,22 +111,14 @@ static void mangle_contents(struct sk_buff *skb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Unusual, but possible case. */
|
/* Unusual, but possible case. */
|
||||||
static int enlarge_skb(struct sk_buff **pskb, unsigned int extra)
|
static int enlarge_skb(struct sk_buff *skb, unsigned int extra)
|
||||||
{
|
{
|
||||||
struct sk_buff *nskb;
|
if (skb->len + extra > 65535)
|
||||||
|
|
||||||
if ((*pskb)->len + extra > 65535)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
nskb = skb_copy_expand(*pskb, skb_headroom(*pskb), extra, GFP_ATOMIC);
|
if (pskb_expand_head(skb, 0, extra - skb_tailroom(skb), GFP_ATOMIC))
|
||||||
if (!nskb)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Transfer socket to new skb. */
|
|
||||||
if ((*pskb)->sk)
|
|
||||||
skb_set_owner_w(nskb, (*pskb)->sk);
|
|
||||||
kfree_skb(*pskb);
|
|
||||||
*pskb = nskb;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +131,7 @@ static int enlarge_skb(struct sk_buff **pskb, unsigned int extra)
|
|||||||
*
|
*
|
||||||
* */
|
* */
|
||||||
int
|
int
|
||||||
nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
|
nf_nat_mangle_tcp_packet(struct sk_buff *skb,
|
||||||
struct nf_conn *ct,
|
struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned int match_offset,
|
unsigned int match_offset,
|
||||||
@ -147,37 +139,37 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
|
|||||||
const char *rep_buffer,
|
const char *rep_buffer,
|
||||||
unsigned int rep_len)
|
unsigned int rep_len)
|
||||||
{
|
{
|
||||||
struct rtable *rt = (struct rtable *)(*pskb)->dst;
|
struct rtable *rt = (struct rtable *)skb->dst;
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
struct tcphdr *tcph;
|
struct tcphdr *tcph;
|
||||||
int oldlen, datalen;
|
int oldlen, datalen;
|
||||||
|
|
||||||
if (!skb_make_writable(pskb, (*pskb)->len))
|
if (!skb_make_writable(skb, skb->len))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (rep_len > match_len &&
|
if (rep_len > match_len &&
|
||||||
rep_len - match_len > skb_tailroom(*pskb) &&
|
rep_len - match_len > skb_tailroom(skb) &&
|
||||||
!enlarge_skb(pskb, rep_len - match_len))
|
!enlarge_skb(skb, rep_len - match_len))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
SKB_LINEAR_ASSERT(*pskb);
|
SKB_LINEAR_ASSERT(skb);
|
||||||
|
|
||||||
iph = ip_hdr(*pskb);
|
iph = ip_hdr(skb);
|
||||||
tcph = (void *)iph + iph->ihl*4;
|
tcph = (void *)iph + iph->ihl*4;
|
||||||
|
|
||||||
oldlen = (*pskb)->len - iph->ihl*4;
|
oldlen = skb->len - iph->ihl*4;
|
||||||
mangle_contents(*pskb, iph->ihl*4 + tcph->doff*4,
|
mangle_contents(skb, iph->ihl*4 + tcph->doff*4,
|
||||||
match_offset, match_len, rep_buffer, rep_len);
|
match_offset, match_len, rep_buffer, rep_len);
|
||||||
|
|
||||||
datalen = (*pskb)->len - iph->ihl*4;
|
datalen = skb->len - iph->ihl*4;
|
||||||
if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
|
if (skb->ip_summed != CHECKSUM_PARTIAL) {
|
||||||
if (!(rt->rt_flags & RTCF_LOCAL) &&
|
if (!(rt->rt_flags & RTCF_LOCAL) &&
|
||||||
(*pskb)->dev->features & NETIF_F_V4_CSUM) {
|
skb->dev->features & NETIF_F_V4_CSUM) {
|
||||||
(*pskb)->ip_summed = CHECKSUM_PARTIAL;
|
skb->ip_summed = CHECKSUM_PARTIAL;
|
||||||
(*pskb)->csum_start = skb_headroom(*pskb) +
|
skb->csum_start = skb_headroom(skb) +
|
||||||
skb_network_offset(*pskb) +
|
skb_network_offset(skb) +
|
||||||
iph->ihl * 4;
|
iph->ihl * 4;
|
||||||
(*pskb)->csum_offset = offsetof(struct tcphdr, check);
|
skb->csum_offset = offsetof(struct tcphdr, check);
|
||||||
tcph->check = ~tcp_v4_check(datalen,
|
tcph->check = ~tcp_v4_check(datalen,
|
||||||
iph->saddr, iph->daddr, 0);
|
iph->saddr, iph->daddr, 0);
|
||||||
} else {
|
} else {
|
||||||
@ -188,7 +180,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
|
|||||||
datalen, 0));
|
datalen, 0));
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
nf_proto_csum_replace2(&tcph->check, *pskb,
|
nf_proto_csum_replace2(&tcph->check, skb,
|
||||||
htons(oldlen), htons(datalen), 1);
|
htons(oldlen), htons(datalen), 1);
|
||||||
|
|
||||||
if (rep_len != match_len) {
|
if (rep_len != match_len) {
|
||||||
@ -197,7 +189,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
|
|||||||
(int)rep_len - (int)match_len,
|
(int)rep_len - (int)match_len,
|
||||||
ct, ctinfo);
|
ct, ctinfo);
|
||||||
/* Tell TCP window tracking about seq change */
|
/* Tell TCP window tracking about seq change */
|
||||||
nf_conntrack_tcp_update(*pskb, ip_hdrlen(*pskb),
|
nf_conntrack_tcp_update(skb, ip_hdrlen(skb),
|
||||||
ct, CTINFO2DIR(ctinfo));
|
ct, CTINFO2DIR(ctinfo));
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@ -215,7 +207,7 @@ EXPORT_SYMBOL(nf_nat_mangle_tcp_packet);
|
|||||||
* should be fairly easy to do.
|
* should be fairly easy to do.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
nf_nat_mangle_udp_packet(struct sk_buff **pskb,
|
nf_nat_mangle_udp_packet(struct sk_buff *skb,
|
||||||
struct nf_conn *ct,
|
struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned int match_offset,
|
unsigned int match_offset,
|
||||||
@ -223,48 +215,48 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb,
|
|||||||
const char *rep_buffer,
|
const char *rep_buffer,
|
||||||
unsigned int rep_len)
|
unsigned int rep_len)
|
||||||
{
|
{
|
||||||
struct rtable *rt = (struct rtable *)(*pskb)->dst;
|
struct rtable *rt = (struct rtable *)skb->dst;
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
struct udphdr *udph;
|
struct udphdr *udph;
|
||||||
int datalen, oldlen;
|
int datalen, oldlen;
|
||||||
|
|
||||||
/* UDP helpers might accidentally mangle the wrong packet */
|
/* UDP helpers might accidentally mangle the wrong packet */
|
||||||
iph = ip_hdr(*pskb);
|
iph = ip_hdr(skb);
|
||||||
if ((*pskb)->len < iph->ihl*4 + sizeof(*udph) +
|
if (skb->len < iph->ihl*4 + sizeof(*udph) +
|
||||||
match_offset + match_len)
|
match_offset + match_len)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!skb_make_writable(pskb, (*pskb)->len))
|
if (!skb_make_writable(skb, skb->len))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (rep_len > match_len &&
|
if (rep_len > match_len &&
|
||||||
rep_len - match_len > skb_tailroom(*pskb) &&
|
rep_len - match_len > skb_tailroom(skb) &&
|
||||||
!enlarge_skb(pskb, rep_len - match_len))
|
!enlarge_skb(skb, rep_len - match_len))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
iph = ip_hdr(*pskb);
|
iph = ip_hdr(skb);
|
||||||
udph = (void *)iph + iph->ihl*4;
|
udph = (void *)iph + iph->ihl*4;
|
||||||
|
|
||||||
oldlen = (*pskb)->len - iph->ihl*4;
|
oldlen = skb->len - iph->ihl*4;
|
||||||
mangle_contents(*pskb, iph->ihl*4 + sizeof(*udph),
|
mangle_contents(skb, iph->ihl*4 + sizeof(*udph),
|
||||||
match_offset, match_len, rep_buffer, rep_len);
|
match_offset, match_len, rep_buffer, rep_len);
|
||||||
|
|
||||||
/* update the length of the UDP packet */
|
/* update the length of the UDP packet */
|
||||||
datalen = (*pskb)->len - iph->ihl*4;
|
datalen = skb->len - iph->ihl*4;
|
||||||
udph->len = htons(datalen);
|
udph->len = htons(datalen);
|
||||||
|
|
||||||
/* fix udp checksum if udp checksum was previously calculated */
|
/* fix udp checksum if udp checksum was previously calculated */
|
||||||
if (!udph->check && (*pskb)->ip_summed != CHECKSUM_PARTIAL)
|
if (!udph->check && skb->ip_summed != CHECKSUM_PARTIAL)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
|
if (skb->ip_summed != CHECKSUM_PARTIAL) {
|
||||||
if (!(rt->rt_flags & RTCF_LOCAL) &&
|
if (!(rt->rt_flags & RTCF_LOCAL) &&
|
||||||
(*pskb)->dev->features & NETIF_F_V4_CSUM) {
|
skb->dev->features & NETIF_F_V4_CSUM) {
|
||||||
(*pskb)->ip_summed = CHECKSUM_PARTIAL;
|
skb->ip_summed = CHECKSUM_PARTIAL;
|
||||||
(*pskb)->csum_start = skb_headroom(*pskb) +
|
skb->csum_start = skb_headroom(skb) +
|
||||||
skb_network_offset(*pskb) +
|
skb_network_offset(skb) +
|
||||||
iph->ihl * 4;
|
iph->ihl * 4;
|
||||||
(*pskb)->csum_offset = offsetof(struct udphdr, check);
|
skb->csum_offset = offsetof(struct udphdr, check);
|
||||||
udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
|
udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
|
||||||
datalen, IPPROTO_UDP,
|
datalen, IPPROTO_UDP,
|
||||||
0);
|
0);
|
||||||
@ -278,7 +270,7 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb,
|
|||||||
udph->check = CSUM_MANGLED_0;
|
udph->check = CSUM_MANGLED_0;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
nf_proto_csum_replace2(&udph->check, *pskb,
|
nf_proto_csum_replace2(&udph->check, skb,
|
||||||
htons(oldlen), htons(datalen), 1);
|
htons(oldlen), htons(datalen), 1);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -330,7 +322,7 @@ sack_adjust(struct sk_buff *skb,
|
|||||||
|
|
||||||
/* TCP SACK sequence number adjustment */
|
/* TCP SACK sequence number adjustment */
|
||||||
static inline unsigned int
|
static inline unsigned int
|
||||||
nf_nat_sack_adjust(struct sk_buff **pskb,
|
nf_nat_sack_adjust(struct sk_buff *skb,
|
||||||
struct tcphdr *tcph,
|
struct tcphdr *tcph,
|
||||||
struct nf_conn *ct,
|
struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo)
|
enum ip_conntrack_info ctinfo)
|
||||||
@ -338,17 +330,17 @@ nf_nat_sack_adjust(struct sk_buff **pskb,
|
|||||||
unsigned int dir, optoff, optend;
|
unsigned int dir, optoff, optend;
|
||||||
struct nf_conn_nat *nat = nfct_nat(ct);
|
struct nf_conn_nat *nat = nfct_nat(ct);
|
||||||
|
|
||||||
optoff = ip_hdrlen(*pskb) + sizeof(struct tcphdr);
|
optoff = ip_hdrlen(skb) + sizeof(struct tcphdr);
|
||||||
optend = ip_hdrlen(*pskb) + tcph->doff * 4;
|
optend = ip_hdrlen(skb) + tcph->doff * 4;
|
||||||
|
|
||||||
if (!skb_make_writable(pskb, optend))
|
if (!skb_make_writable(skb, optend))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dir = CTINFO2DIR(ctinfo);
|
dir = CTINFO2DIR(ctinfo);
|
||||||
|
|
||||||
while (optoff < optend) {
|
while (optoff < optend) {
|
||||||
/* Usually: option, length. */
|
/* Usually: option, length. */
|
||||||
unsigned char *op = (*pskb)->data + optoff;
|
unsigned char *op = skb->data + optoff;
|
||||||
|
|
||||||
switch (op[0]) {
|
switch (op[0]) {
|
||||||
case TCPOPT_EOL:
|
case TCPOPT_EOL:
|
||||||
@ -365,7 +357,7 @@ nf_nat_sack_adjust(struct sk_buff **pskb,
|
|||||||
if (op[0] == TCPOPT_SACK &&
|
if (op[0] == TCPOPT_SACK &&
|
||||||
op[1] >= 2+TCPOLEN_SACK_PERBLOCK &&
|
op[1] >= 2+TCPOLEN_SACK_PERBLOCK &&
|
||||||
((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0)
|
((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0)
|
||||||
sack_adjust(*pskb, tcph, optoff+2,
|
sack_adjust(skb, tcph, optoff+2,
|
||||||
optoff+op[1], &nat->seq[!dir]);
|
optoff+op[1], &nat->seq[!dir]);
|
||||||
optoff += op[1];
|
optoff += op[1];
|
||||||
}
|
}
|
||||||
@ -375,7 +367,7 @@ nf_nat_sack_adjust(struct sk_buff **pskb,
|
|||||||
|
|
||||||
/* TCP sequence number adjustment. Returns 1 on success, 0 on failure */
|
/* TCP sequence number adjustment. Returns 1 on success, 0 on failure */
|
||||||
int
|
int
|
||||||
nf_nat_seq_adjust(struct sk_buff **pskb,
|
nf_nat_seq_adjust(struct sk_buff *skb,
|
||||||
struct nf_conn *ct,
|
struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo)
|
enum ip_conntrack_info ctinfo)
|
||||||
{
|
{
|
||||||
@ -390,10 +382,10 @@ nf_nat_seq_adjust(struct sk_buff **pskb,
|
|||||||
this_way = &nat->seq[dir];
|
this_way = &nat->seq[dir];
|
||||||
other_way = &nat->seq[!dir];
|
other_way = &nat->seq[!dir];
|
||||||
|
|
||||||
if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph)))
|
if (!skb_make_writable(skb, ip_hdrlen(skb) + sizeof(*tcph)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
tcph = (void *)(*pskb)->data + ip_hdrlen(*pskb);
|
tcph = (void *)skb->data + ip_hdrlen(skb);
|
||||||
if (after(ntohl(tcph->seq), this_way->correction_pos))
|
if (after(ntohl(tcph->seq), this_way->correction_pos))
|
||||||
newseq = htonl(ntohl(tcph->seq) + this_way->offset_after);
|
newseq = htonl(ntohl(tcph->seq) + this_way->offset_after);
|
||||||
else
|
else
|
||||||
@ -405,8 +397,8 @@ nf_nat_seq_adjust(struct sk_buff **pskb,
|
|||||||
else
|
else
|
||||||
newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before);
|
newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before);
|
||||||
|
|
||||||
nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0);
|
nf_proto_csum_replace4(&tcph->check, skb, tcph->seq, newseq, 0);
|
||||||
nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0);
|
nf_proto_csum_replace4(&tcph->check, skb, tcph->ack_seq, newack, 0);
|
||||||
|
|
||||||
pr_debug("Adjusting sequence number from %u->%u, ack from %u->%u\n",
|
pr_debug("Adjusting sequence number from %u->%u, ack from %u->%u\n",
|
||||||
ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
|
ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
|
||||||
@ -415,10 +407,10 @@ nf_nat_seq_adjust(struct sk_buff **pskb,
|
|||||||
tcph->seq = newseq;
|
tcph->seq = newseq;
|
||||||
tcph->ack_seq = newack;
|
tcph->ack_seq = newack;
|
||||||
|
|
||||||
if (!nf_nat_sack_adjust(pskb, tcph, ct, ctinfo))
|
if (!nf_nat_sack_adjust(skb, tcph, ct, ctinfo))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
nf_conntrack_tcp_update(*pskb, ip_hdrlen(*pskb), ct, dir);
|
nf_conntrack_tcp_update(skb, ip_hdrlen(skb), ct, dir);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ MODULE_DESCRIPTION("IRC (DCC) NAT helper");
|
|||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_ALIAS("ip_nat_irc");
|
MODULE_ALIAS("ip_nat_irc");
|
||||||
|
|
||||||
static unsigned int help(struct sk_buff **pskb,
|
static unsigned int help(struct sk_buff *skb,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
unsigned int matchoff,
|
unsigned int matchoff,
|
||||||
unsigned int matchlen,
|
unsigned int matchlen,
|
||||||
@ -58,7 +58,7 @@ static unsigned int help(struct sk_buff **pskb,
|
|||||||
pr_debug("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n",
|
pr_debug("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n",
|
||||||
buffer, NIPQUAD(ip), port);
|
buffer, NIPQUAD(ip), port);
|
||||||
|
|
||||||
ret = nf_nat_mangle_tcp_packet(pskb, exp->master, ctinfo,
|
ret = nf_nat_mangle_tcp_packet(skb, exp->master, ctinfo,
|
||||||
matchoff, matchlen, buffer,
|
matchoff, matchlen, buffer,
|
||||||
strlen(buffer));
|
strlen(buffer));
|
||||||
if (ret != NF_ACCEPT)
|
if (ret != NF_ACCEPT)
|
||||||
|
@ -110,7 +110,7 @@ static void pptp_nat_expected(struct nf_conn *ct,
|
|||||||
|
|
||||||
/* outbound packets == from PNS to PAC */
|
/* outbound packets == from PNS to PAC */
|
||||||
static int
|
static int
|
||||||
pptp_outbound_pkt(struct sk_buff **pskb,
|
pptp_outbound_pkt(struct sk_buff *skb,
|
||||||
struct nf_conn *ct,
|
struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
struct PptpControlHeader *ctlh,
|
struct PptpControlHeader *ctlh,
|
||||||
@ -175,7 +175,7 @@ pptp_outbound_pkt(struct sk_buff **pskb,
|
|||||||
ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid));
|
ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid));
|
||||||
|
|
||||||
/* mangle packet */
|
/* mangle packet */
|
||||||
if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
|
if (nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
|
||||||
cid_off + sizeof(struct pptp_pkt_hdr) +
|
cid_off + sizeof(struct pptp_pkt_hdr) +
|
||||||
sizeof(struct PptpControlHeader),
|
sizeof(struct PptpControlHeader),
|
||||||
sizeof(new_callid), (char *)&new_callid,
|
sizeof(new_callid), (char *)&new_callid,
|
||||||
@ -213,7 +213,7 @@ pptp_exp_gre(struct nf_conntrack_expect *expect_orig,
|
|||||||
|
|
||||||
/* inbound packets == from PAC to PNS */
|
/* inbound packets == from PAC to PNS */
|
||||||
static int
|
static int
|
||||||
pptp_inbound_pkt(struct sk_buff **pskb,
|
pptp_inbound_pkt(struct sk_buff *skb,
|
||||||
struct nf_conn *ct,
|
struct nf_conn *ct,
|
||||||
enum ip_conntrack_info ctinfo,
|
enum ip_conntrack_info ctinfo,
|
||||||
struct PptpControlHeader *ctlh,
|
struct PptpControlHeader *ctlh,
|
||||||
@ -268,7 +268,7 @@ pptp_inbound_pkt(struct sk_buff **pskb,
|
|||||||
pr_debug("altering peer call id from 0x%04x to 0x%04x\n",
|
pr_debug("altering peer call id from 0x%04x to 0x%04x\n",
|
||||||
ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid));
|
ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid));
|
||||||
|
|
||||||
if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
|
if (nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
|
||||||
pcid_off + sizeof(struct pptp_pkt_hdr) +
|
pcid_off + sizeof(struct pptp_pkt_hdr) +
|
||||||
sizeof(struct PptpControlHeader),
|
sizeof(struct PptpControlHeader),
|
||||||
sizeof(new_pcid), (char *)&new_pcid,
|
sizeof(new_pcid), (char *)&new_pcid,
|
||||||
|
@ -98,21 +98,21 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple,
|
|||||||
|
|
||||||
/* manipulate a GRE packet according to maniptype */
|
/* manipulate a GRE packet according to maniptype */
|
||||||
static int
|
static int
|
||||||
gre_manip_pkt(struct sk_buff **pskb, unsigned int iphdroff,
|
gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff,
|
||||||
const struct nf_conntrack_tuple *tuple,
|
const struct nf_conntrack_tuple *tuple,
|
||||||
enum nf_nat_manip_type maniptype)
|
enum nf_nat_manip_type maniptype)
|
||||||
{
|
{
|
||||||
struct gre_hdr *greh;
|
struct gre_hdr *greh;
|
||||||
struct gre_hdr_pptp *pgreh;
|
struct gre_hdr_pptp *pgreh;
|
||||||
struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
|
struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
|
||||||
unsigned int hdroff = iphdroff + iph->ihl * 4;
|
unsigned int hdroff = iphdroff + iph->ihl * 4;
|
||||||
|
|
||||||
/* pgreh includes two optional 32bit fields which are not required
|
/* pgreh includes two optional 32bit fields which are not required
|
||||||
* to be there. That's where the magic '8' comes from */
|
* to be there. That's where the magic '8' comes from */
|
||||||
if (!skb_make_writable(pskb, hdroff + sizeof(*pgreh) - 8))
|
if (!skb_make_writable(skb, hdroff + sizeof(*pgreh) - 8))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
greh = (void *)(*pskb)->data + hdroff;
|
greh = (void *)skb->data + hdroff;
|
||||||
pgreh = (struct gre_hdr_pptp *)greh;
|
pgreh = (struct gre_hdr_pptp *)greh;
|
||||||
|
|
||||||
/* we only have destination manip of a packet, since 'source key'
|
/* we only have destination manip of a packet, since 'source key'
|
||||||
|
@ -52,20 +52,20 @@ icmp_unique_tuple(struct nf_conntrack_tuple *tuple,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
icmp_manip_pkt(struct sk_buff **pskb,
|
icmp_manip_pkt(struct sk_buff *skb,
|
||||||
unsigned int iphdroff,
|
unsigned int iphdroff,
|
||||||
const struct nf_conntrack_tuple *tuple,
|
const struct nf_conntrack_tuple *tuple,
|
||||||
enum nf_nat_manip_type maniptype)
|
enum nf_nat_manip_type maniptype)
|
||||||
{
|
{
|
||||||
struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
|
struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
|
||||||
struct icmphdr *hdr;
|
struct icmphdr *hdr;
|
||||||
unsigned int hdroff = iphdroff + iph->ihl*4;
|
unsigned int hdroff = iphdroff + iph->ihl*4;
|
||||||
|
|
||||||
if (!skb_make_writable(pskb, hdroff + sizeof(*hdr)))
|
if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
hdr = (struct icmphdr *)((*pskb)->data + hdroff);
|
hdr = (struct icmphdr *)(skb->data + hdroff);
|
||||||
nf_proto_csum_replace2(&hdr->checksum, *pskb,
|
nf_proto_csum_replace2(&hdr->checksum, skb,
|
||||||
hdr->un.echo.id, tuple->src.u.icmp.id, 0);
|
hdr->un.echo.id, tuple->src.u.icmp.id, 0);
|
||||||
hdr->un.echo.id = tuple->src.u.icmp.id;
|
hdr->un.echo.id = tuple->src.u.icmp.id;
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -88,12 +88,12 @@ tcp_unique_tuple(struct nf_conntrack_tuple *tuple,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
tcp_manip_pkt(struct sk_buff **pskb,
|
tcp_manip_pkt(struct sk_buff *skb,
|
||||||
unsigned int iphdroff,
|
unsigned int iphdroff,
|
||||||
const struct nf_conntrack_tuple *tuple,
|
const struct nf_conntrack_tuple *tuple,
|
||||||
enum nf_nat_manip_type maniptype)
|
enum nf_nat_manip_type maniptype)
|
||||||
{
|
{
|
||||||
struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
|
struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
|
||||||
struct tcphdr *hdr;
|
struct tcphdr *hdr;
|
||||||
unsigned int hdroff = iphdroff + iph->ihl*4;
|
unsigned int hdroff = iphdroff + iph->ihl*4;
|
||||||
__be32 oldip, newip;
|
__be32 oldip, newip;
|
||||||
@ -103,14 +103,14 @@ tcp_manip_pkt(struct sk_buff **pskb,
|
|||||||
/* this could be a inner header returned in icmp packet; in such
|
/* this could be a inner header returned in icmp packet; in such
|
||||||
cases we cannot update the checksum field since it is outside of
|
cases we cannot update the checksum field since it is outside of
|
||||||
the 8 bytes of transport layer headers we are guaranteed */
|
the 8 bytes of transport layer headers we are guaranteed */
|
||||||
if ((*pskb)->len >= hdroff + sizeof(struct tcphdr))
|
if (skb->len >= hdroff + sizeof(struct tcphdr))
|
||||||
hdrsize = sizeof(struct tcphdr);
|
hdrsize = sizeof(struct tcphdr);
|
||||||
|
|
||||||
if (!skb_make_writable(pskb, hdroff + hdrsize))
|
if (!skb_make_writable(skb, hdroff + hdrsize))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
iph = (struct iphdr *)((*pskb)->data + iphdroff);
|
iph = (struct iphdr *)(skb->data + iphdroff);
|
||||||
hdr = (struct tcphdr *)((*pskb)->data + hdroff);
|
hdr = (struct tcphdr *)(skb->data + hdroff);
|
||||||
|
|
||||||
if (maniptype == IP_NAT_MANIP_SRC) {
|
if (maniptype == IP_NAT_MANIP_SRC) {
|
||||||
/* Get rid of src ip and src pt */
|
/* Get rid of src ip and src pt */
|
||||||
@ -132,8 +132,8 @@ tcp_manip_pkt(struct sk_buff **pskb,
|
|||||||
if (hdrsize < sizeof(*hdr))
|
if (hdrsize < sizeof(*hdr))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
|
nf_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1);
|
||||||
nf_proto_csum_replace2(&hdr->check, *pskb, oldport, newport, 0);
|
nf_proto_csum_replace2(&hdr->check, skb, oldport, newport, 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,22 +86,22 @@ udp_unique_tuple(struct nf_conntrack_tuple *tuple,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
udp_manip_pkt(struct sk_buff **pskb,
|
udp_manip_pkt(struct sk_buff *skb,
|
||||||
unsigned int iphdroff,
|
unsigned int iphdroff,
|
||||||
const struct nf_conntrack_tuple *tuple,
|
const struct nf_conntrack_tuple *tuple,
|
||||||
enum nf_nat_manip_type maniptype)
|
enum nf_nat_manip_type maniptype)
|
||||||
{
|
{
|
||||||
struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
|
struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
|
||||||
struct udphdr *hdr;
|
struct udphdr *hdr;
|
||||||
unsigned int hdroff = iphdroff + iph->ihl*4;
|
unsigned int hdroff = iphdroff + iph->ihl*4;
|
||||||
__be32 oldip, newip;
|
__be32 oldip, newip;
|
||||||
__be16 *portptr, newport;
|
__be16 *portptr, newport;
|
||||||
|
|
||||||
if (!skb_make_writable(pskb, hdroff + sizeof(*hdr)))
|
if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
iph = (struct iphdr *)((*pskb)->data + iphdroff);
|
iph = (struct iphdr *)(skb->data + iphdroff);
|
||||||
hdr = (struct udphdr *)((*pskb)->data + hdroff);
|
hdr = (struct udphdr *)(skb->data + hdroff);
|
||||||
|
|
||||||
if (maniptype == IP_NAT_MANIP_SRC) {
|
if (maniptype == IP_NAT_MANIP_SRC) {
|
||||||
/* Get rid of src ip and src pt */
|
/* Get rid of src ip and src pt */
|
||||||
@ -116,9 +116,9 @@ udp_manip_pkt(struct sk_buff **pskb,
|
|||||||
newport = tuple->dst.u.udp.port;
|
newport = tuple->dst.u.udp.port;
|
||||||
portptr = &hdr->dest;
|
portptr = &hdr->dest;
|
||||||
}
|
}
|
||||||
if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) {
|
if (hdr->check || skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||||
nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
|
nf_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1);
|
||||||
nf_proto_csum_replace2(&hdr->check, *pskb, *portptr, newport,
|
nf_proto_csum_replace2(&hdr->check, skb, *portptr, newport,
|
||||||
0);
|
0);
|
||||||
if (!hdr->check)
|
if (!hdr->check)
|
||||||
hdr->check = CSUM_MANGLED_0;
|
hdr->check = CSUM_MANGLED_0;
|
||||||
|
@ -37,7 +37,7 @@ static int unknown_unique_tuple(struct nf_conntrack_tuple *tuple,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
unknown_manip_pkt(struct sk_buff **pskb,
|
unknown_manip_pkt(struct sk_buff *skb,
|
||||||
unsigned int iphdroff,
|
unsigned int iphdroff,
|
||||||
const struct nf_conntrack_tuple *tuple,
|
const struct nf_conntrack_tuple *tuple,
|
||||||
enum nf_nat_manip_type maniptype)
|
enum nf_nat_manip_type maniptype)
|
||||||
|
@ -65,7 +65,7 @@ static struct xt_table nat_table = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Source NAT */
|
/* Source NAT */
|
||||||
static unsigned int ipt_snat_target(struct sk_buff **pskb,
|
static unsigned int ipt_snat_target(struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
@ -78,7 +78,7 @@ static unsigned int ipt_snat_target(struct sk_buff **pskb,
|
|||||||
|
|
||||||
NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING);
|
NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING);
|
||||||
|
|
||||||
ct = nf_ct_get(*pskb, &ctinfo);
|
ct = nf_ct_get(skb, &ctinfo);
|
||||||
|
|
||||||
/* Connection must be valid and new. */
|
/* Connection must be valid and new. */
|
||||||
NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
|
NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
|
||||||
@ -107,7 +107,7 @@ static void warn_if_extra_mangle(__be32 dstip, __be32 srcip)
|
|||||||
ip_rt_put(rt);
|
ip_rt_put(rt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int ipt_dnat_target(struct sk_buff **pskb,
|
static unsigned int ipt_dnat_target(struct sk_buff *skb,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
@ -121,14 +121,14 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb,
|
|||||||
NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
|
NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
|
||||||
hooknum == NF_IP_LOCAL_OUT);
|
hooknum == NF_IP_LOCAL_OUT);
|
||||||
|
|
||||||
ct = nf_ct_get(*pskb, &ctinfo);
|
ct = nf_ct_get(skb, &ctinfo);
|
||||||
|
|
||||||
/* Connection must be valid and new. */
|
/* Connection must be valid and new. */
|
||||||
NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
|
NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
|
||||||
|
|
||||||
if (hooknum == NF_IP_LOCAL_OUT &&
|
if (hooknum == NF_IP_LOCAL_OUT &&
|
||||||
mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)
|
mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)
|
||||||
warn_if_extra_mangle(ip_hdr(*pskb)->daddr,
|
warn_if_extra_mangle(ip_hdr(skb)->daddr,
|
||||||
mr->range[0].min_ip);
|
mr->range[0].min_ip);
|
||||||
|
|
||||||
return nf_nat_setup_info(ct, &mr->range[0], hooknum);
|
return nf_nat_setup_info(ct, &mr->range[0], hooknum);
|
||||||
@ -204,7 +204,7 @@ alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum)
|
|||||||
return nf_nat_setup_info(ct, &range, hooknum);
|
return nf_nat_setup_info(ct, &range, hooknum);
|
||||||
}
|
}
|
||||||
|
|
||||||
int nf_nat_rule_find(struct sk_buff **pskb,
|
int nf_nat_rule_find(struct sk_buff *skb,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum,
|
||||||
const struct net_device *in,
|
const struct net_device *in,
|
||||||
const struct net_device *out,
|
const struct net_device *out,
|
||||||
@ -212,7 +212,7 @@ int nf_nat_rule_find(struct sk_buff **pskb,
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = ipt_do_table(pskb, hooknum, in, out, &nat_table);
|
ret = ipt_do_table(skb, hooknum, in, out, &nat_table);
|
||||||
|
|
||||||
if (ret == NF_ACCEPT) {
|
if (ret == NF_ACCEPT) {
|
||||||
if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum)))
|
if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum)))
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user