diff options
60 files changed, 1073 insertions, 644 deletions
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index 45b735af8c93..91fcd7955fe3 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c @@ -2261,7 +2261,7 @@ static int __devinit amb_probe(struct pci_dev *pci_dev, const struct pci_device_ int err; // read resources from PCI configuration space - u8 irq = pci_dev->irq; + unsigned int irq = pci_dev->irq; if (pci_dev->device == PCI_DEVICE_ID_MADGE_AMBASSADOR_BAD) { PRINTK (KERN_ERR, "skipped broken (PLX rev 2) card"); @@ -2439,6 +2439,8 @@ static struct pci_device_id amb_pci_tbl[] = { { 0, } }; +MODULE_DEVICE_TABLE(pci, amb_pci_tbl); + static struct pci_driver amb_driver = { .name = "amb", .probe = amb_probe, diff --git a/drivers/atm/he.c b/drivers/atm/he.c index 74b490bc49f7..6338181cf0dd 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c @@ -3051,6 +3051,8 @@ static struct pci_device_id he_pci_tbl[] = { { 0, } }; +MODULE_DEVICE_TABLE(pci, he_pci_tbl); + static struct pci_driver he_driver = { .name = "he", .probe = he_init_one, diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c index a3f3c2413f2f..7ae054473c23 100644 --- a/drivers/atm/horizon.c +++ b/drivers/atm/horizon.c @@ -2913,6 +2913,8 @@ static struct pci_device_id hrz_pci_tbl[] = { { 0, } }; +MODULE_DEVICE_TABLE(pci, hrz_pci_tbl); + static struct pci_driver hrz_driver = { .name = "horizon", .probe = hrz_probe, diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index 6fc5b1de8b52..72ea27c15933 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -3820,6 +3820,8 @@ static struct pci_device_id idt77252_pci_tbl[] = { 0, } }; +MODULE_DEVICE_TABLE(pci, idt77252_pci_tbl); + static struct pci_driver idt77252_driver = { .name = "idt77252", .id_table = idt77252_pci_tbl, diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 54ef5f941eb9..1d26a4db1360 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -34,6 +34,8 @@ #include <linux/ptrace.h> #include <linux/ioport.h> #include <linux/spinlock.h> +#include <linux/moduleparam.h> + #include <linux/skbuff.h> #include <asm/io.h> @@ -54,11 +56,11 @@ /* Bit map of interrupts to choose from */ -static u_int irq_mask = 0x86bc; +static unsigned int irq_mask = 0x86bc; static int irq_list[4] = { -1 }; -MODULE_PARM(irq_mask, "i"); -MODULE_PARM(irq_list, "1-4i"); +module_param(irq_mask, uint, 0); +module_param_array(irq_list, int, NULL, 0); MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth driver for the Anycom BlueCard (LSE039/LSE041)"); diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 305e030eb447..37bdb030e0fd 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -34,6 +34,7 @@ #include <linux/ptrace.h> #include <linux/ioport.h> #include <linux/spinlock.h> +#include <linux/moduleparam.h> #include <linux/skbuff.h> #include <linux/string.h> @@ -63,11 +64,11 @@ /* Bit map of interrupts to choose from */ -static u_int irq_mask = 0xffff; +static unsigned int irq_mask = 0xffff; static int irq_list[4] = { -1 }; -MODULE_PARM(irq_mask, "i"); -MODULE_PARM(irq_list, "1-4i"); +module_param(irq_mask, uint, 0); +module_param_array(irq_list, int, NULL, 0); MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>, Jose Orlando Pereira <jop@di.uminho.pt>"); MODULE_DESCRIPTION("Bluetooth driver for the 3Com Bluetooth PCMCIA card"); diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index f039c84e8218..7814bed545e2 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -33,6 +33,7 @@ #include <linux/ptrace.h> #include <linux/ioport.h> #include <linux/spinlock.h> +#include <linux/moduleparam.h> #include <linux/skbuff.h> #include <linux/string.h> @@ -59,11 +60,11 @@ /* Bit map of interrupts to choose from */ -static u_int irq_mask = 0xffff; +static unsigned int irq_mask = 0xffff; static int irq_list[4] = { -1 }; -MODULE_PARM(irq_mask, "i"); -MODULE_PARM(irq_list, "1-4i"); +module_param(irq_mask, uint, 0); +module_param_array(irq_list, int, NULL, 0); MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth driver for Bluetooth PCMCIA cards with HCI UART interface"); diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 91e0a2edf720..8579aebc7949 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -33,6 +33,7 @@ #include <linux/ptrace.h> #include <linux/ioport.h> #include <linux/spinlock.h> +#include <linux/moduleparam.h> #include <linux/skbuff.h> #include <linux/string.h> @@ -59,11 +60,11 @@ /* Bit map of interrupts to choose from */ -static u_int irq_mask = 0xffff; +static unsigned int irq_mask = 0xffff; static int irq_list[4] = { -1 }; -MODULE_PARM(irq_mask, "i"); -MODULE_PARM(irq_list, "1-4i"); +module_param(irq_mask, uint, 0); +module_param_array(irq_list, int, NULL, 0); MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth driver for Nokia Connectivity Card DTL-1"); diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index d0c197db3ce4..3cbcc4155651 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c @@ -101,8 +101,12 @@ static struct usb_device_id blacklist_ids[] = { { USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE }, /* Broadcom BCM2035 */ + { USB_DEVICE(0x0a5c, 0x2009), .driver_info = HCI_RESET | HCI_BROKEN_ISOC }, { USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET | HCI_BROKEN_ISOC }, + /* Microsoft Wireless Transceiver for Bluetooth 2.0 */ + { USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET | HCI_BROKEN_ISOC }, + /* ISSC Bluetooth Adapter v3.1 */ { USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET }, diff --git a/drivers/isdn/i4l/isdn_x25iface.c b/drivers/isdn/i4l/isdn_x25iface.c index da1d2fb9fc8d..4ab7600cf9c1 100644 --- a/drivers/isdn/i4l/isdn_x25iface.c +++ b/drivers/isdn/i4l/isdn_x25iface.c @@ -21,6 +21,7 @@ #include <linux/netdevice.h> #include <linux/concap.h> #include <linux/wanrouter.h> +#include <net/x25device.h> #include "isdn_x25iface.h" /* for debugging messages not to cause an oops when device pointer is NULL*/ @@ -191,12 +192,9 @@ int isdn_x25iface_receive(struct concap_proto *cprot, struct sk_buff *skb) IX25DEBUG( "isdn_x25iface_receive %s \n", MY_DEVNAME(cprot->net_dev) ); if ( ( (ix25_pdata_t*) (cprot->proto_data) ) -> state == WAN_CONNECTED ){ - skb -> dev = cprot -> net_dev; - skb -> protocol = htons(ETH_P_X25); - skb -> pkt_type = PACKET_HOST; if( skb_push(skb, 1)){ skb -> data[0]=0x00; - skb -> mac.raw = skb -> data; + skb->protocol = x25_type_trans(skb, cprot->net_dev); netif_rx(skb); return 0; } @@ -224,10 +222,7 @@ int isdn_x25iface_connect_ind(struct concap_proto *cprot) *state_p = WAN_CONNECTED; if( skb ){ *( skb_put(skb, 1) ) = 0x01; - skb -> mac.raw = skb -> data; - skb -> dev = cprot -> net_dev; - skb -> protocol = htons(ETH_P_X25); - skb -> pkt_type = PACKET_HOST; + skb->protocol = x25_type_trans(skb, cprot->net_dev); netif_rx(skb); return 0; } else { @@ -256,10 +251,7 @@ int isdn_x25iface_disconn_ind(struct concap_proto *cprot) skb = dev_alloc_skb(1); if( skb ){ *( skb_put(skb, 1) ) = 0x02; - skb -> mac.raw = skb -> data; - skb -> dev = cprot -> net_dev; - skb -> protocol = htons(ETH_P_X25); - skb -> pkt_type = PACKET_HOST; + skb->protocol = x25_type_trans(skb, cprot->net_dev); netif_rx(skb); return 0; } else { diff --git a/drivers/net/ethertap.c b/drivers/net/ethertap.c index ef47c5c9aff8..24f237b22a75 100644 --- a/drivers/net/ethertap.c +++ b/drivers/net/ethertap.c @@ -124,7 +124,7 @@ static int ethertap_open(struct net_device *dev) struct net_local *lp = netdev_priv(dev); if (ethertap_debug > 2) - printk(KERN_DEBUG "%s: Doing ethertap_open()...", dev->name); + printk(KERN_DEBUG "%s: Doing ethertap_open()...\n", dev->name); lp->nl = netlink_kernel_create(dev->base_addr, ethertap_rx); if (lp->nl == NULL) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 02cc93065231..6bd0f97a76d7 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -60,8 +60,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.11" -#define DRV_MODULE_RELDATE "October 20, 2004" +#define DRV_MODULE_VERSION "3.13" +#define DRV_MODULE_RELDATE "November 1, 2004" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -418,6 +418,20 @@ static void tg3_enable_ints(struct tg3 *tp) tg3_cond_int(tp); } +/* tg3_restart_ints + * similar to tg3_enable_ints, but it can return without flushing the + * PIO write which reenables interrupts + */ +static void tg3_restart_ints(struct tg3 *tp) +{ + tw32(TG3PCI_MISC_HOST_CTRL, + (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT)); + tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000); + mmiowb(); + + tg3_cond_int(tp); +} + static inline void tg3_netif_stop(struct tg3 *tp) { netif_poll_disable(tp->dev); @@ -2145,7 +2159,16 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED; } else if (mac_status & (MAC_STATUS_PCS_SYNCED | MAC_STATUS_SIGNAL_DET)) { - sg_dig_status = tr32(SG_DIG_STATUS); + int i; + + /* Giver time to negotiate (~200ms) */ + for (i = 0; i < 40000; i++) { + sg_dig_status = tr32(SG_DIG_STATUS); + if (sg_dig_status & (0x3)) + break; + udelay(5); + } + mac_status = tr32(MAC_STATUS); if ((sg_dig_status & (1 << 1)) && (mac_status & MAC_STATUS_PCS_SYNCED)) { @@ -2730,6 +2753,7 @@ next_pkt_nopost: tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW, sw_idx); } + mmiowb(); return received; } @@ -2788,7 +2812,7 @@ static int tg3_poll(struct net_device *netdev, int *budget) if (done) { spin_lock_irqsave(&tp->lock, flags); __netif_rx_complete(netdev); - tg3_enable_ints(tp); + tg3_restart_ints(tp); spin_unlock_irqrestore(&tp->lock, flags); } @@ -3177,6 +3201,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); out_unlock: + mmiowb(); spin_unlock_irqrestore(&tp->tx_lock, flags); dev->trans_start = jiffies; @@ -8224,7 +8249,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, spin_lock_init(&tp->indirect_lock); INIT_WORK(&tp->reset_task, tg3_reset_task, tp); - tp->regs = ioremap(tg3reg_base, tg3reg_len); + tp->regs = ioremap_nocache(tg3reg_base, tg3reg_len); if (tp->regs == 0UL) { printk(KERN_ERR PFX "Cannot map device registers, " "aborting.\n"); diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c index 9b26d3c0e9cc..5b48cd8568f5 100644 --- a/drivers/net/wan/cycx_x25.c +++ b/drivers/net/wan/cycx_x25.c @@ -92,6 +92,8 @@ #include <linux/cyclomx.h> /* Cyclom 2X common user API definitions */ #include <linux/cycx_x25.h> /* X.25 firmware API definitions */ +#include <net/x25device.h> + /* Defines & Macros */ #define CYCX_X25_MAX_CMD_RETRY 5 #define CYCX_X25_CHAN_MTU 2048 /* unfragmented logical channel MTU */ @@ -1486,11 +1488,7 @@ static void cycx_x25_chan_send_event(struct net_device *dev, u8 event) ptr = skb_put(skb, 1); *ptr = event; - skb->dev = dev; - skb->protocol = htons(ETH_P_X25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; - + skb->protocol = x25_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; /* timestamp */ } diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 982bb213e686..e998cfff9fa9 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -519,7 +519,6 @@ inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv, struct net_device *dev) dpriv->rx_skbuff[dirty] = skb; if (skb) { skb->protocol = hdlc_type_trans(skb, dev); - skb->mac.raw = skb->data; rx_fd->data = pci_map_single(dpriv->pci_priv->pdev, skb->data, len, PCI_DMA_FROMDEVICE); } else { diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c index 5231063c9d64..07e5eef1fe0f 100644 --- a/drivers/net/wan/hdlc_x25.c +++ b/drivers/net/wan/hdlc_x25.c @@ -23,6 +23,8 @@ #include <linux/rtnetlink.h> #include <linux/hdlc.h> +#include <net/x25device.h> + /* These functions are callbacks called by LAPB layer */ static void x25_connect_disconnect(struct net_device *dev, int reason, int code) @@ -38,11 +40,7 @@ static void x25_connect_disconnect(struct net_device *dev, int reason, int code) ptr = skb_put(skb, 1); *ptr = code; - skb->dev = dev; - skb->protocol = htons(ETH_P_X25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; - + skb->protocol = x25_type_trans(skb, dev); netif_rx(skb); } @@ -74,11 +72,7 @@ static int x25_data_indication(struct net_device *dev, struct sk_buff *skb) ptr = skb->data; *ptr = 0; - skb->dev = dev; - skb->protocol = htons(ETH_P_X25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; - + skb->protocol = x25_type_trans(skb, dev); return netif_rx(skb); } diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index c8f3187e12c9..7f2e3653c5e5 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -43,6 +43,8 @@ #include <linux/lapb.h> #include <linux/init.h> +#include <net/x25device.h> + static char bcast_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* If this number is made larger, check that the temporary string buffer @@ -137,11 +139,7 @@ static int lapbeth_data_indication(struct net_device *dev, struct sk_buff *skb) ptr = skb->data; *ptr = 0x00; - skb->dev = dev; - skb->protocol = htons(ETH_P_X25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; - + skb->protocol = x25_type_trans(skb, dev); skb->dev->last_rx = jiffies; return netif_rx(skb); } @@ -233,11 +231,7 @@ static void lapbeth_connected(struct net_device *dev, int reason) ptr = skb_put(skb, 1); *ptr = 0x01; - skb->dev = dev; - skb->protocol = htons(ETH_P_X25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; - + skb->protocol = x25_type_trans(skb, dev); skb->dev->last_rx = jiffies; netif_rx(skb); } @@ -255,11 +249,7 @@ static void lapbeth_disconnected(struct net_device *dev, int reason) ptr = skb_put(skb, 1); *ptr = 0x02; - skb->dev = dev; - skb->protocol = htons(ETH_P_X25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; - + skb->protocol = x25_type_trans(skb, dev); skb->dev->last_rx = jiffies; netif_rx(skb); } diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 57e9758eb83f..03f4331b4a22 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -34,6 +34,8 @@ #include <linux/init.h> #include "x25_asy.h" +#include <net/x25device.h> + static struct net_device **x25_asy_devs; static int x25_asy_maxdev = SL_NRUNIT; @@ -209,10 +211,8 @@ static void x25_asy_bump(struct x25_asy *sl) return; } skb_push(skb,1); /* LAPB internal control */ - skb->dev = sl->dev; memcpy(skb_put(skb,count), sl->rbuff, count); - skb->mac.raw=skb->data; - skb->protocol=htons(ETH_P_X25); + skb->protocol = x25_type_trans(skb, sl->dev); if((err=lapb_data_received(skb->dev, skb))!=LAPB_OK) { kfree_skb(skb); @@ -419,11 +419,7 @@ static void x25_asy_connected(struct net_device *dev, int reason) ptr = skb_put(skb, 1); *ptr = 0x01; - skb->dev = sl->dev; - skb->protocol = htons(ETH_P_X25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; - + skb->protocol = x25_type_trans(skb, sl->dev); netif_rx(skb); sl->dev->last_rx = jiffies; } @@ -442,11 +438,7 @@ static void x25_asy_disconnected(struct net_device *dev, int reason) ptr = skb_put(skb, 1); *ptr = 0x02; - skb->dev = sl->dev; - skb->protocol = htons(ETH_P_X25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; - + skb->protocol = x25_type_trans(skb, sl->dev); netif_rx(skb); sl->dev->last_rx = jiffies; } diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index defc7bc472d9..642fb5c614cb 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -413,6 +413,10 @@ extern void ipt_unregister_target(struct ipt_target *target); extern int ipt_register_match(struct ipt_match *match); extern void ipt_unregister_match(struct ipt_match *match); +extern struct ipt_target * +__ipt_find_target_lock(const char *name, int *error); +extern void __ipt_mutex_up(void); + /* Furniture shopping... */ struct ipt_table { diff --git a/include/linux/tc_act/tc_ipt.h b/include/linux/tc_act/tc_ipt.h new file mode 100644 index 000000000000..4b6f7b6c7a79 --- /dev/null +++ b/include/linux/tc_act/tc_ipt.h @@ -0,0 +1,21 @@ +#ifndef __LINUX_TC_IPT_H +#define __LINUX_TC_IPT_H + +#include <linux/pkt_cls.h> + +#define TCA_ACT_IPT 6 + +enum +{ + TCA_IPT_UNSPEC, + TCA_IPT_TABLE, + TCA_IPT_HOOK, + TCA_IPT_INDEX, + TCA_IPT_CNT, + TCA_IPT_TM, + TCA_IPT_TARG, + __TCA_IPT_MAX +}; +#define TCA_IPT_MAX (__TCA_IPT_MAX - 1) + +#endif diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 2c9995af03a8..ef0ecb6c75fd 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -161,7 +161,9 @@ struct hci_conn { extern struct hci_proto *hci_proto[]; extern struct list_head hci_dev_list; +extern struct list_head hci_cb_list; extern rwlock_t hci_dev_list_lock; +extern rwlock_t hci_cb_list_lock; /* ----- Inquiry cache ----- */ #define INQUIRY_CACHE_AGE_MAX (HZ*30) // 30 seconds @@ -229,7 +231,7 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c) struct hci_conn_hash *h = &hdev->conn_hash; list_del(&c->list); if (c->type == ACL_LINK) - h->acl_num++; + h->acl_num--; else h->sco_num--; } @@ -491,6 +493,50 @@ static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status) int hci_register_proto(struct hci_proto *hproto); int hci_unregister_proto(struct hci_proto *hproto); + +/* ----- HCI callbacks ----- */ +struct hci_cb { + struct list_head list; + + char *name; + + void (*auth_cfm) (struct hci_conn *conn, __u8 status); + void (*encrypt_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt); +}; + +static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status) +{ + struct list_head *p; + + hci_proto_auth_cfm(conn, status); + + read_lock_bh(&hci_cb_list_lock); + list_for_each(p, &hci_cb_list) { + struct hci_cb *cb = list_entry(p, struct hci_cb, list); + if (cb->auth_cfm) + cb->auth_cfm(conn, status); + } + read_unlock_bh(&hci_cb_list_lock); +} + +static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt) +{ + struct list_head *p; + + hci_proto_encrypt_cfm(conn, status); + + read_lock_bh(&hci_cb_list_lock); + list_for_each(p, &hci_cb_list) { + struct hci_cb *cb = list_entry(p, struct hci_cb, list); + if (cb->encrypt_cfm) + cb->encrypt_cfm(conn, status, encrypt); + } + read_unlock_bh(&hci_cb_list_lock); +} + +int hci_register_cb(struct hci_cb *hcb); +int hci_unregister_cb(struct hci_cb *hcb); + int hci_register_notifier(struct notifier_block *nb); int hci_unregister_notifier(struct notifier_block *nb); diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 9ba24794afe3..4c441ef94d93 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -8,7 +8,7 @@ #include <asm/types.h> /* For __uXX types */ -#define IP_VS_VERSION_CODE 0x010200 +#define IP_VS_VERSION_CODE 0x010201 #define NVERSION(version) \ (version >> 16) & 0xFF, \ (version >> 8) & 0xFF, \ diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index 2eb89bbaec87..3dd20562a196 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h @@ -3,6 +3,7 @@ #include <linux/pkt_cls.h> #include <net/sch_generic.h> +#include <net/act_api.h> /* Basic packet classifier frontend definitions. */ @@ -41,4 +42,189 @@ cls_set_class(struct tcf_proto *tp, unsigned long *clp, return old_cl; } +static inline void +tcf_bind_filter(struct tcf_proto *tp, struct tcf_result *r, unsigned long base) +{ + unsigned long cl; + + cl = tp->q->ops->cl_ops->bind_tcf(tp->q, base, r->classid); + cl = cls_set_class(tp, &r->class, cl); + if (cl) + tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); +} + +static inline void +tcf_unbind_filter(struct tcf_proto *tp, struct tcf_result *r) +{ + unsigned long cl; + + if ((cl = __cls_set_class(&r->class, 0)) != 0) + tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); +} + +#ifdef CONFIG_NET_CLS_ACT +static inline int +tcf_change_act_police(struct tcf_proto *tp, struct tc_action **action, + struct rtattr *act_police_tlv, struct rtattr *rate_tlv) +{ + int ret; + struct tc_action *act; + + act = kmalloc(sizeof(*act), GFP_KERNEL); + if (NULL == act) + return -ENOMEM; + memset(act, 0, sizeof(*act)); + + ret = tcf_action_init_1(act_police_tlv, rate_tlv, act, "police", + TCA_ACT_NOREPLACE, TCA_ACT_BIND); + if (ret < 0) { + tcf_action_destroy(act, TCA_ACT_UNBIND); + return ret; + } + + act->type = TCA_OLD_COMPAT; + + if (*action) { + tcf_tree_lock(tp); + act = xchg(action, act); + tcf_tree_unlock(tp); + + tcf_action_destroy(act, TCA_ACT_UNBIND); + } else + *action = act; + + return 0; +} + +static inline int +tcf_change_act(struct tcf_proto *tp, struct tc_action **action, + struct rtattr *act_tlv, struct rtattr *rate_tlv) +{ + int ret; + struct tc_action *act; + + act = kmalloc(sizeof(*act), GFP_KERNEL); + if (NULL == act) + return -ENOMEM; + memset(act, 0, sizeof(*act)); + + ret = tcf_action_init(act_tlv, rate_tlv, act, NULL, + TCA_ACT_NOREPLACE, TCA_ACT_BIND); + if (ret < 0) { + tcf_action_destroy(act, TCA_ACT_UNBIND); + return ret; + } + + if (*action) { + tcf_tree_lock(tp); + act = xchg(action, act); + tcf_tree_unlock(tp); + + tcf_action_destroy(act, TCA_ACT_UNBIND); + } else + *action = act; + + return 0; +} + +static inline int +tcf_dump_act(struct sk_buff *skb, struct tc_action *action, + int act_type, int compat_type) +{ + /* + * again for backward compatible mode - we want + * to work with both old and new modes of entering + * tc data even if iproute2 was newer - jhs + */ + if (action) { + struct rtattr * p_rta = (struct rtattr*) skb->tail; + + if (action->type != TCA_OLD_COMPAT) { + RTA_PUT(skb, act_type, 0, NULL); + if (tcf_action_dump(skb, action, 0, 0) < 0) + goto rtattr_failure; + } else { + RTA_PUT(skb, compat_type, 0, NULL); + if (tcf_action_dump_old(skb, action, 0, 0) < 0) + goto rtattr_failure; + } + + p_rta->rta_len = skb->tail - (u8*)p_rta; + } + return 0; + +rtattr_failure: + return -1; +} +#endif /* CONFIG_NET_CLS_ACT */ + +#ifdef CONFIG_NET_CLS_IND +static inline int +tcf_change_indev(struct tcf_proto *tp, char *indev, struct rtattr *indev_tlv) +{ + if (RTA_PAYLOAD(indev_tlv) >= IFNAMSIZ) { + printk("cls: bad indev name %s\n", (char *) RTA_DATA(indev_tlv)); + return -EINVAL; + } + + memset(indev, 0, IFNAMSIZ); + sprintf(indev, "%s", (char *) RTA_DATA(indev_tlv)); + + return 0; +} + +static inline int +tcf_match_indev(struct sk_buff *skb, char *indev) +{ + if (0 != indev[0]) { + if (NULL == skb->input_dev) + return 0; + else if (0 != strcmp(indev, skb->input_dev->name)) + return 0; + } + + return 1; +} +#endif /* CONFIG_NET_CLS_IND */ + +#ifdef CONFIG_NET_CLS_POLICE +static inline int +tcf_change_police(struct tcf_proto *tp, struct tcf_police **police, + struct rtattr *police_tlv, struct rtattr *rate_tlv) +{ + struct tcf_police *p = tcf_police_locate(police_tlv, rate_tlv); + + if (*police) { + tcf_tree_lock(tp); + p = xchg(police, p); + tcf_tree_unlock(tp); + + tcf_police_release(p, TCA_ACT_UNBIND); + } else + *police = p; + + return 0; +} + +static inline int +tcf_dump_police(struct sk_buff *skb, struct tcf_police *police, + int police_type) +{ + if (police) { + struct rtattr * p_rta = (struct rtattr*) skb->tail; + + RTA_PUT(skb, police_type, 0, NULL); + + if (tcf_police_dump(skb, police) < 0) + goto rtattr_failure; + + p_rta->rta_len = skb->tail - (u8*)p_rta; + } + return 0; + +rtattr_failure: + return -1; +} +#endif /* CONFIG_NET_CLS_POLICE */ + #endif diff --git a/include/net/tc_act/tc_ipt.h b/include/net/tc_act/tc_ipt.h new file mode 100644 index 000000000000..02eccebd55ae --- /dev/null +++ b/include/net/tc_act/tc_ipt.h @@ -0,0 +1,16 @@ +#ifndef __NET_TC_IPT_H +#define __NET_TC_IPT_H + +#include <net/act_api.h> + +struct ipt_entry_target; + +struct tcf_ipt +{ + tca_gen(ipt); + u32 hook; + char *tname; + struct ipt_entry_target *t; +}; + +#endif diff --git a/include/net/x25device.h b/include/net/x25device.h new file mode 100644 index 000000000000..cf36a20ea3c5 --- /dev/null +++ b/include/net/x25device.h @@ -0,0 +1,17 @@ +#ifndef _X25DEVICE_H +#define _X25DEVICE_H + +#include <linux/if_ether.h> +#include <linux/if_packet.h> +#include <linux/skbuff.h> + +static inline unsigned short x25_type_trans(struct sk_buff *skb, + struct net_device *dev) +{ + skb->mac.raw = skb->data; + skb->input_dev = skb->dev = dev; + skb->pkt_type = PACKET_HOST; + + return htons(ETH_P_X25); +} +#endif diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index ead778b5dceb..942bde0f7479 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -484,26 +484,13 @@ int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) veth->h_vlan_proto, veth->h_vlan_TCI, veth->h_vlan_encapsulated_proto); #endif - skb->dev = VLAN_DEV_INFO(dev)->real_dev; - - { - /* Please note, dev_queue_xmit consumes the pkt regardless of the - * error value. So, will copy the skb first and free if successful. - */ - struct sk_buff* skb2 = skb_get(skb); - int rv = dev_queue_xmit(skb2); - if (rv == 0) { - /* Was success, need to free the skb reference since we bumped up the - * user count above. - */ + stats->tx_packets++; /* for statics only */ + stats->tx_bytes += skb->len; - stats->tx_packets++; /* for statics only */ - stats->tx_bytes += skb->len; + skb->dev = VLAN_DEV_INFO(dev)->real_dev; + dev_queue_xmit(skb); - kfree_skb(skb); - } - return rv; - } + return 0; } int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) diff --git a/net/Kconfig b/net/Kconfig index d682d05cbf3f..155754c8e144 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -219,6 +219,10 @@ source "net/bridge/netfilter/Kconfig" endif +config XFRM + bool + depends on NET + source "net/xfrm/Kconfig" source "net/sctp/Kconfig" diff --git a/net/Makefile b/net/Makefile index a46436e0fcc2..8e2bdc025ab8 100644 --- a/net/Makefile +++ b/net/Makefile @@ -15,7 +15,8 @@ obj-$(CONFIG_NET) += $(tmp-y) # LLC has to be linked before the files in net/802/ obj-$(CONFIG_LLC) += llc/ obj-$(CONFIG_NET) += ethernet/ 802/ sched/ netlink/ -obj-$(CONFIG_INET) += ipv4/ xfrm/ +obj-$(CONFIG_INET) += ipv4/ +obj-$(CONFIG_XFRM) += xfrm/ obj-$(CONFIG_UNIX) += unix/ ifneq ($(CONFIG_IPV6),) obj-y += ipv6/ diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 588cbe1ec16f..8eada1ca17d8 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -78,13 +78,6 @@ static inline void __atalk_insert_socket(struct sock *sk) sk_add_node(sk, &atalk_sockets); } -static inline void atalk_insert_socket(struct sock *sk) -{ - write_lock_bh(&atalk_sockets_lock); - __atalk_insert_socket(sk); - write_unlock_bh(&atalk_sockets_lock); -} - static inline void atalk_remove_socket(struct sock *sk) { write_lock_bh(&atalk_sockets_lock); diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c index 82c3c451fbd9..1090ac6dc058 100644 --- a/net/ax25/ax25_route.c +++ b/net/ax25/ax25_route.c @@ -41,22 +41,6 @@ static rwlock_t ax25_route_lock = RW_LOCK_UNLOCKED; static ax25_route *ax25_get_route(ax25_address *, struct net_device *); -/* - * small macro to drop non-digipeated digipeaters and reverse path - */ -static inline void ax25_route_invert(ax25_digi *in, ax25_digi *out) -{ - int k; - - for (k = 0; k < in->ndigi; k++) - if (!in->repeated[k]) - break; - - in->ndigi = k; - - ax25_digi_invert(in, out); -} - void ax25_rt_device_down(struct net_device *dev) { ax25_route *s, *t, *ax25_rt; diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 53e90098c20c..8ff58bc2bf27 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -51,7 +51,7 @@ #define BT_DBG(D...) #endif -#define VERSION "2.6" +#define VERSION "2.7" struct proc_dir_entry *proc_bt; EXPORT_SYMBOL(proc_bt); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index e7d26b0f9afa..830a7a73bb2b 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -65,6 +65,10 @@ rwlock_t hci_task_lock = RW_LOCK_UNLOCKED; LIST_HEAD(hci_dev_list); rwlock_t hci_dev_list_lock = RW_LOCK_UNLOCKED; +/* HCI callback list */ +LIST_HEAD(hci_cb_list); +rwlock_t hci_cb_list_lock = RW_LOCK_UNLOCKED; + /* HCI protocols */ #define HCI_MAX_PROTO 2 struct hci_proto *hci_proto[HCI_MAX_PROTO]; @@ -930,6 +934,30 @@ int hci_unregister_proto(struct hci_proto *hp) } EXPORT_SYMBOL(hci_unregister_proto); +int hci_register_cb(struct hci_cb *cb) +{ + BT_DBG("%p name %s", cb, cb->name); + + write_lock_bh(&hci_cb_list_lock); + list_add(&cb->list, &hci_cb_list); + write_unlock_bh(&hci_cb_list_lock); + + return 0; +} +EXPORT_SYMBOL(hci_register_cb); + +int hci_unregister_cb(struct hci_cb *cb) +{ + BT_DBG("%p name %s", cb, cb->name); + + write_lock_bh(&hci_cb_list_lock); + list_del(&cb->list); + write_unlock_bh(&hci_cb_list_lock); + + return 0; +} +EXPORT_SYMBOL(hci_unregister_cb); + static int hci_send_frame(struct sk_buff *skb) { struct hci_dev *hdev = (struct hci_dev *) skb->dev; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 22b435cd7d62..93f34e3ede10 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -739,7 +739,7 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s conn->link_mode |= HCI_LM_AUTH; clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); - hci_proto_auth_cfm(conn, ev->status); + hci_auth_cfm(conn, ev->status); if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { if (!ev->status) { @@ -751,7 +751,7 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s sizeof(cp), &cp); } else { clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); - hci_proto_encrypt_cfm(conn, ev->status); + hci_encrypt_cfm(conn, ev->status, 0x00); } } } @@ -780,7 +780,7 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff * } clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); - hci_proto_encrypt_cfm(conn, ev->status); + hci_encrypt_cfm(conn, ev->status, ev->encrypt); } hci_dev_unlock(hdev); diff --git a/net/core/dev.c b/net/core/dev.c index a9e9c01258e2..b62614574c7c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1261,6 +1261,11 @@ int dev_queue_xmit(struct sk_buff *skb) struct Qdisc *q; int rc = -ENOMEM; + /* Disable soft irqs for various locks below. Also + * stops preemption for RCU. + */ + local_bh_disable(); + if (skb_shinfo(skb)->frag_list && !(dev->features & NETIF_F_FRAGLIST) && __skb_linearize(skb, GFP_ATOMIC)) @@ -1285,12 +1290,6 @@ int dev_queue_xmit(struct sk_buff *skb) if (skb_checksum_help(skb, 0)) goto out_kfree_skb; - - /* Disable soft irqs for various locks below. Also - * stops preemption for RCU. - */ - local_bh_disable(); - /* Updates of qdisc are serialized by queue_lock. * The struct Qdisc which is pointed to by qdisc is now a * rcu structure - it may be accessed without acquiring @@ -3242,7 +3241,6 @@ EXPORT_SYMBOL(__dev_get_by_index); EXPORT_SYMBOL(__dev_get_by_name); EXPORT_SYMBOL(__dev_remove_pack); EXPORT_SYMBOL(__skb_linearize); -EXPORT_SYMBOL(call_netdevice_notifiers); EXPORT_SYMBOL(dev_add_pack); EXPORT_SYMBOL(dev_alloc_name); EXPORT_SYMBOL(dev_close); diff --git a/net/core/netfilter.c b/net/core/netfilter.c index 9db8b4467f9d..b7f017877f7b 100644 --- a/net/core/netfilter.c +++ b/net/core/netfilter.c @@ -673,6 +673,7 @@ int ip_route_me_harder(struct sk_buff **pskb) return 0; } +EXPORT_SYMBOL(ip_route_me_harder); int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len) { @@ -818,7 +819,6 @@ void __init netfilter_init(void) } EXPORT_SYMBOL(ip_ct_attach); -EXPORT_SYMBOL(ip_route_me_harder); EXPORT_SYMBOL(nf_getsockopt); EXPORT_SYMBOL(nf_hook_slow); EXPORT_SYMBOL(nf_hooks); diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 270ceb7e104e..d62bb4cf6ba9 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -301,6 +301,7 @@ config SYN_COOKIES config INET_AH tristate "IP: AH transformation" + depends on INET select XFRM select CRYPTO select CRYPTO_HMAC @@ -313,6 +314,7 @@ config INET_AH config INET_ESP tristate "IP: ESP transformation" + depends on INET select XFRM select CRYPTO select CRYPTO_HMAC @@ -326,6 +328,7 @@ config INET_ESP config INET_IPCOMP tristate "IP: IPComp transformation" + depends on INET select XFRM select INET_TUNNEL select CRYPTO @@ -338,6 +341,7 @@ config INET_IPCOMP config INET_TUNNEL tristate "IP: tunnel transformation" + depends on INET select XFRM ---help--- Support for generic IP tunnel transformation, which is required by @@ -345,5 +349,14 @@ config INET_TUNNEL If unsure, say Y. +config IP_TCPDIAG + tristate "IP: TCP socket monitoring interface" + default y + ---help--- + Support for TCP socket monitoring interface used by native Linux + tools such as ss. + + If unsure, say Y. + source "net/ipv4/ipvs/Kconfig" diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 38f75099674f..e0f24f50ed3e 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile @@ -6,7 +6,7 @@ obj-y := utils.o route.o inetpeer.o protocol.o \ ip_input.o ip_fragment.o ip_forward.o ip_options.o \ ip_output.o ip_sockglue.o \ tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o tcp_minisocks.o \ - tcp_diag.o datagram.o raw.o udp.o arp.o icmp.o devinet.o af_inet.o igmp.o \ + datagram.o raw.o udp.o arp.o icmp.o devinet.o af_inet.o igmp.o \ sysctl_net_ipv4.o fib_frontend.o fib_semantics.o fib_hash.o obj-$(CONFIG_PROC_FS) += proc.o @@ -22,6 +22,7 @@ obj-$(CONFIG_INET_TUNNEL) += xfrm4_tunnel.o obj-$(CONFIG_IP_PNP) += ipconfig.o obj-$(CONFIG_NETFILTER) += netfilter/ obj-$(CONFIG_IP_VS) += ipvs/ +obj-$(CONFIG_IP_TCPDIAG) += tcp_diag.o obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ xfrm4_output.o diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index b3a6e6427c00..d14a4e342de3 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -312,6 +312,7 @@ destroy_conntrack(struct nf_conntrack *nfct) } kmem_cache_free(ip_conntrack_expect_cachep, ct->master); } + CONNTRACK_STAT_INC(delete); WRITE_UNLOCK(&ip_conntrack_lock); if (master) @@ -320,7 +321,6 @@ destroy_conntrack(struct nf_conntrack *nfct) DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct); kmem_cache_free(ip_conntrack_cachep, ct); atomic_dec(&ip_conntrack_count); - CONNTRACK_STAT_INC(delete); } static void death_by_timeout(unsigned long ul_conntrack) diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 3e601a80d580..e470729ab5e3 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -477,6 +477,18 @@ ipt_find_target_lock(const char *name, int *error, struct semaphore *mutex) return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex); } +struct ipt_target * +__ipt_find_target_lock(const char *name, int *error) +{ + return ipt_find_target_lock(name,error,&ipt_mutex); +} + +void +__ipt_mutex_up(void) +{ + up(&ipt_mutex); +} + /* All zeroes == unconditional rule. */ static inline int unconditional(const struct ipt_ip *ip) @@ -1877,6 +1889,8 @@ EXPORT_SYMBOL(ipt_unregister_match); EXPORT_SYMBOL(ipt_do_table); EXPORT_SYMBOL(ipt_register_target); EXPORT_SYMBOL(ipt_unregister_target); +EXPORT_SYMBOL_GPL(__ipt_find_target_lock); +EXPORT_SYMBOL_GPL(__ipt_mutex_up); module_init(init); module_exit(fini); diff --git a/net/ipv4/netfilter/ipt_tcpmss.c b/net/ipv4/netfilter/ipt_tcpmss.c index 5cda547e011e..4dc9b16ab4a3 100644 --- a/net/ipv4/netfilter/ipt_tcpmss.c +++ b/net/ipv4/netfilter/ipt_tcpmss.c @@ -87,18 +87,6 @@ match(const struct sk_buff *skb, info->invert, hotdrop); } -static inline int find_syn_match(const struct ipt_entry_match *m) -{ - const struct ipt_tcp *tcpinfo = (const struct ipt_tcp *)m->data; - - if (strcmp(m->u.kernel.match->name, "tcp") == 0 - && (tcpinfo->flg_cmp & TH_SYN) - && !(tcpinfo->invflags & IPT_TCP_INV_FLAGS)) - return 1; - - return 0; -} - static int checkentry(const char *tablename, const struct ipt_ip *ip, diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 928ba3b541ed..0f59b48ed4cb 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2152,6 +2152,8 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info) info->tcpi_total_retrans = tp->total_retrans; } +EXPORT_SYMBOL_GPL(tcp_get_info); + int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { @@ -2358,8 +2360,6 @@ void __init tcp_init(void) printk(KERN_INFO "TCP: Hash tables configured " "(established %d bind %d)\n", tcp_ehash_size << 1, tcp_bhash_size); - - tcpdiag_init(); } EXPORT_SYMBOL(tcp_accept); diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c index 5c2bf6a08fcd..6c719559baab 100644 --- a/net/ipv4/tcp_diag.c +++ b/net/ipv4/tcp_diag.c @@ -776,9 +776,19 @@ static void tcpdiag_rcv(struct sock *sk, int len) } } -void __init tcpdiag_init(void) +static int __init tcpdiag_init(void) { tcpnl = netlink_kernel_create(NETLINK_TCPDIAG, tcpdiag_rcv); if (tcpnl == NULL) - panic("tcpdiag_init: Cannot create netlink socket."); + return -ENOMEM; + return 0; } + +static void __exit tcpdiag_exit(void) +{ + sock_release(tcpnl->sk_socket); +} + +module_init(tcpdiag_init); +module_exit(tcpdiag_exit); +MODULE_LICENSE("GPL"); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3df3ada30e6c..9efcbbd11566 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -535,6 +535,8 @@ inline struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, return sk; } +EXPORT_SYMBOL_GPL(tcp_v4_lookup); + static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb) { return secure_tcp_sequence_number(skb->nh.iph->daddr, diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 2bdc1975c319..2076d201f492 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -1075,7 +1075,3 @@ EXPORT_SYMBOL(tcp_child_process); EXPORT_SYMBOL(tcp_create_openreq_child); EXPORT_SYMBOL(tcp_timewait_state_process); EXPORT_SYMBOL(tcp_tw_deschedule); - -#ifdef CONFIG_SYSCTL -EXPORT_SYMBOL(sysctl_tcp_tw_recycle); -#endif diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index 47e54d4218df..2d3849c38a0f 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c @@ -9,6 +9,7 @@ * */ +#include <linux/module.h> #include <linux/string.h> #include <net/inet_ecn.h> #include <net/ip.h> @@ -19,6 +20,8 @@ int xfrm4_rcv(struct sk_buff *skb) return xfrm4_rcv_encap(skb, 0); } +EXPORT_SYMBOL(xfrm4_rcv); + static inline void ipip_ecn_decapsulate(struct sk_buff *skb) { struct iphdr *outer_iph = skb->nh.iph; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 7112e8406a28..d6cadb2ceede 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -364,6 +364,8 @@ inline struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport, return sk; } +EXPORT_SYMBOL_GPL(tcp_v6_lookup); + /* * Open request hash tables. diff --git a/net/irda/qos.c b/net/irda/qos.c index b02d2db0350c..d37dd2548325 100644 --- a/net/irda/qos.c +++ b/net/irda/qos.c @@ -211,17 +211,6 @@ static int msb_index (__u16 word) return index; } -static inline __u32 byte_value(__u8 byte, __u32 *array) -{ - int index; - - ASSERT(array != NULL, return -1;); - - index = msb_index(byte); - - return index_value(index, array); -} - /* * Function value_lower_bits (value, array) * diff --git a/net/sched/Kconfig b/net/sched/Kconfig index e9306fb27983..2fe4fd4e34cf 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -393,7 +393,7 @@ config NET_ACT_GACT ---help--- You must have new iproute2 to use this feature. This adds simple filtering actions like drop, accept etc. - + config GACT_PROB bool "generic Actions probability" depends on NET_ACT_GACT @@ -407,6 +407,13 @@ config NET_ACT_MIRRED requires new iproute2 This allows packets to be mirrored or redirected to netdevices +config NET_ACT_IPT + tristate "iptables Actions" + depends on NET_CLS_ACT && NETFILTER && IP_NF_IPTABLES + ---help--- + requires new iproute2 + This allows iptables targets to be used by tc filters + config NET_ACT_PEDIT tristate "Generic Packet Editor Actions" depends on NET_CLS_ACT diff --git a/net/sched/Makefile b/net/sched/Makefile index f69bb707f4a0..fad3a43a8939 100644 --- a/net/sched/Makefile +++ b/net/sched/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_NET_ACT_POLICE) += police.o obj-$(CONFIG_NET_CLS_POLICE) += police.o obj-$(CONFIG_NET_ACT_GACT) += gact.o obj-$(CONFIG_NET_ACT_MIRRED) += mirred.o +obj-$(CONFIG_NET_ACT_IPT) += ipt.o obj-$(CONFIG_NET_ACT_PEDIT) += pedit.o obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index 7bb75eb1ee32..faaad5ceced3 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c @@ -56,16 +56,16 @@ struct fw_filter struct fw_filter *next; u32 id; struct tcf_result res; -#ifdef CONFIG_NET_CLS_ACT - struct tc_action *action; #ifdef CONFIG_NET_CLS_IND - char indev[IFNAMSIZ]; -#endif -#else + char indev[IFNAMSIZ]; +#endif /* CONFIG_NET_CLS_IND */ +#ifdef CONFIG_NET_CLS_ACT + struct tc_action *action; +#else /* CONFIG_NET_CLS_ACT */ #ifdef CONFIG_NET_CLS_POLICE struct tcf_police *police; -#endif -#endif +#endif /* CONFIG_NET_CLS_POLICE */ +#endif /* CONFIG_NET_CLS_ACT */ }; static __inline__ int fw_hash(u32 handle) @@ -84,47 +84,39 @@ static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp, u32 id = 0; #endif - if (head == NULL) - goto old_method; - - for (f=head->ht[fw_hash(id)]; f; f=f->next) { - if (f->id == id) { - *res = f->res; -#ifdef CONFIG_NET_CLS_ACT + if (head != NULL) { + for (f=head->ht[fw_hash(id)]; f; f=f->next) { + if (f->id == id) { + *res = f->res; #ifdef CONFIG_NET_CLS_IND - if (0 != f->indev[0]) { - if (NULL == skb->input_dev) { + if (!tcf_match_indev(skb, f->indev)) + continue; +#endif /* CONFIG_NET_CLS_IND */ +#ifdef CONFIG_NET_CLS_ACT + if (f->action) { + int act_res = tcf_action_exec(skb, f->action, res); + if (act_res >= 0) + return act_res; continue; - } else { - if (0 != strcmp(f->indev, skb->input_dev->name)) { - continue; - } } - } -#endif - if (f->action) { - int pol_res = tcf_action_exec(skb, f->action, res); - if (pol_res >= 0) - return pol_res; - } else -#else +#else /* CONFIG_NET_CLS_ACT */ #ifdef CONFIG_NET_CLS_POLICE - if (f->police) - return tcf_police(skb, f->police); -#endif -#endif + if (f->police) + return tcf_police(skb, f->police); +#endif /* CONFIG_NET_CLS_POLICE */ +#endif /* CONFIG_NET_CLS_ACT */ + return 0; + } + } + } else { + /* old method */ + if (id && (TC_H_MAJ(id) == 0 || !(TC_H_MAJ(id^tp->q->handle)))) { + res->classid = id; + res->class = 0; return 0; } } - return -1; -old_method: - if (id && (TC_H_MAJ(id) == 0 || - !(TC_H_MAJ(id^tp->q->handle)))) { - res->classid = id; - res->class = 0; - return 0; - } return -1; } @@ -163,20 +155,17 @@ static void fw_destroy(struct tcf_proto *tp) for (h=0; h<256; h++) { while ((f=head->ht[h]) != NULL) { - unsigned long cl; head->ht[h] = f->next; - - if ((cl = __cls_set_class(&f->res.class, 0)) != 0) - tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); + tcf_unbind_filter(tp, &f->res); #ifdef CONFIG_NET_CLS_ACT - if (f->action) { - tcf_action_destroy(f->action,TCA_ACT_UNBIND); - } -#else + if (f->action) + tcf_action_destroy(f->action, TCA_ACT_UNBIND); +#else /* CONFIG_NET_CLS_ACT */ #ifdef CONFIG_NET_CLS_POLICE - tcf_police_release(f->police,TCA_ACT_UNBIND); -#endif -#endif + if (f->police) + tcf_police_release(f->police, TCA_ACT_UNBIND); +#endif /* CONFIG_NET_CLS_POLICE */ +#endif /* CONFIG_NET_CLS_ACT */ kfree(f); } @@ -195,23 +184,18 @@ static int fw_delete(struct tcf_proto *tp, unsigned long arg) for (fp=&head->ht[fw_hash(f->id)]; *fp; fp = &(*fp)->next) { if (*fp == f) { - unsigned long cl; - tcf_tree_lock(tp); *fp = f->next; tcf_tree_unlock(tp); - - if ((cl = cls_set_class(tp, &f->res.class, 0)) != 0) - tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); + tcf_unbind_filter(tp, &f->res); #ifdef CONFIG_NET_CLS_ACT - if (f->action) { - tcf_action_destroy(f->action,TCA_ACT_UNBIND); - } -#else + if (f->action) + tcf_action_destroy(f->action,TCA_ACT_UNBIND); +#else /* CONFIG_NET_CLS_ACT */ #ifdef CONFIG_NET_CLS_POLICE tcf_police_release(f->police,TCA_ACT_UNBIND); -#endif -#endif +#endif /* CONFIG_NET_CLS_POLICE */ +#endif /* CONFIG_NET_CLS_ACT */ kfree(f); return 0; } @@ -220,21 +204,67 @@ out: return -EINVAL; } +static int +fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f, + struct rtattr **tb, struct rtattr **tca, unsigned long base) +{ + int err = -EINVAL; + + if (tb[TCA_FW_CLASSID-1]) { + if (RTA_PAYLOAD(tb[TCA_FW_CLASSID-1]) != sizeof(u32)) + goto errout; + f->res.classid = *(u32*)RTA_DATA(tb[TCA_FW_CLASSID-1]); + tcf_bind_filter(tp, &f->res, base); + } + +#ifdef CONFIG_NET_CLS_IND + if (tb[TCA_FW_INDEV-1]) { + err = tcf_change_indev(tp, f->indev, tb[TCA_FW_INDEV-1]); + if (err < 0) + goto errout; + } +#endif /* CONFIG_NET_CLS_IND */ + +#ifdef CONFIG_NET_CLS_ACT + if (tb[TCA_FW_POLICE-1]) { + err = tcf_change_act_police(tp, &f->action, tb[TCA_FW_POLICE-1], + tca[TCA_RATE-1]); + if (err < 0) + goto errout; + } + + if (tb[TCA_FW_ACT-1]) { + err = tcf_change_act(tp, &f->action, tb[TCA_FW_ACT-1], + tca[TCA_RATE-1]); + if (err < 0) + goto errout; + } +#else /* CONFIG_NET_CLS_ACT */ +#ifdef CONFIG_NET_CLS_POLICE + if (tb[TCA_FW_POLICE-1]) { + err = tcf_change_police(tp, &f->police, tb[TCA_FW_POLICE-1], + tca[TCA_RATE-1]); + if (err < 0) + goto errout; + } +#endif /* CONFIG_NET_CLS_POLICE */ +#endif /* CONFIG_NET_CLS_ACT */ + + err = 0; +errout: + return err; +} + static int fw_change(struct tcf_proto *tp, unsigned long base, u32 handle, struct rtattr **tca, unsigned long *arg) { struct fw_head *head = (struct fw_head*)tp->root; - struct fw_filter *f; + struct fw_filter *f = (struct fw_filter *) *arg; struct rtattr *opt = tca[TCA_OPTIONS-1]; struct rtattr *tb[TCA_FW_MAX]; int err; -#ifdef CONFIG_NET_CLS_ACT - struct tc_action *act = NULL; - int ret; -#endif - if (!opt) return handle ? -EINVAL : 0; @@ -242,85 +272,10 @@ static int fw_change(struct tcf_proto *tp, unsigned long base, if (rtattr_parse(tb, TCA_FW_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)) < 0) return -EINVAL; - if ((f = (struct fw_filter*)*arg) != NULL) { - /* Node exists: adjust only classid */ - + if (f != NULL) { if (f->id != handle && handle) return -EINVAL; - if (tb[TCA_FW_CLASSID-1]) { - unsigned long cl; - - f->res.classid = *(u32*)RTA_DATA(tb[TCA_FW_CLASSID-1]); - cl = tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid); - cl = cls_set_class(tp, &f->res.class, cl); - if (cl) - tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); - } -#ifdef CONFIG_NET_CLS_ACT - if (tb[TCA_FW_POLICE-1]) { - act = kmalloc(sizeof(*act),GFP_KERNEL); - if (NULL == act) - return -ENOMEM; - - memset(act,0,sizeof(*act)); - ret = tcf_action_init_1(tb[TCA_FW_POLICE-1], tca[TCA_RATE-1] ,act,"police",TCA_ACT_NOREPLACE,TCA_ACT_BIND); - if (0 > ret){ - tcf_action_destroy(act,TCA_ACT_UNBIND); - return ret; - } - act->type = TCA_OLD_COMPAT; - - sch_tree_lock(tp->q); - act = xchg(&f->action, act); - sch_tree_unlock(tp->q); - - tcf_action_destroy(act,TCA_ACT_UNBIND); - - } - - if(tb[TCA_FW_ACT-1]) { - act = kmalloc(sizeof(*act),GFP_KERNEL); - if (NULL == act) - return -ENOMEM; - memset(act,0,sizeof(*act)); - ret = tcf_action_init(tb[TCA_FW_ACT-1], tca[TCA_RATE-1],act,NULL, TCA_ACT_NOREPLACE,TCA_ACT_BIND); - if (0 > ret) { - tcf_action_destroy(act,TCA_ACT_UNBIND); - return ret; - } - - sch_tree_lock(tp->q); - act = xchg(&f->action, act); - sch_tree_unlock(tp->q); - - tcf_action_destroy(act,TCA_ACT_UNBIND); - } -#ifdef CONFIG_NET_CLS_IND - if(tb[TCA_FW_INDEV-1]) { - struct rtattr *idev = tb[TCA_FW_INDEV-1]; - if (RTA_PAYLOAD(idev) >= IFNAMSIZ) { - printk("cls_fw: bad indev name %s\n",(char*)RTA_DATA(idev)); - err = -EINVAL; - goto errout; - } - memset(f->indev,0,IFNAMSIZ); - sprintf(f->indev, "%s", (char*)RTA_DATA(idev)); - } -#endif -#else /* only POLICE defined */ -#ifdef CONFIG_NET_CLS_POLICE - if (tb[TCA_FW_POLICE-1]) { - struct tcf_police *police = tcf_police_locate(tb[TCA_FW_POLICE-1], tca[TCA_RATE-1]); - - tcf_tree_lock(tp); - police = xchg(&f->police, police); - tcf_tree_unlock(tp); - - tcf_police_release(police,TCA_ACT_UNBIND); - } -#endif -#endif - return 0; + return fw_change_attrs(tp, f, tb, tca, base); } if (!handle) @@ -344,45 +299,9 @@ static int fw_change(struct tcf_proto *tp, unsigned long base, f->id = handle; - if (tb[TCA_FW_CLASSID-1]) { - err = -EINVAL; - if (RTA_PAYLOAD(tb[TCA_FW_CLASSID-1]) != 4) - goto errout; - f->res.classid = *(u32*)RTA_DATA(tb[TCA_FW_CLASSID-1]); - cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid)); - } - -#ifdef CONFIG_NET_CLS_ACT - if(tb[TCA_FW_ACT-1]) { - act = kmalloc(sizeof(*act),GFP_KERNEL); - if (NULL == act) - return -ENOMEM; - memset(act,0,sizeof(*act)); - ret = tcf_action_init(tb[TCA_FW_ACT-1], tca[TCA_RATE-1],act,NULL,TCA_ACT_NOREPLACE,TCA_ACT_BIND); - if (0 > ret) { - tcf_action_destroy(act,TCA_ACT_UNBIND); - return ret; - } - f->action= act; - } -#ifdef CONFIG_NET_CLS_IND - if(tb[TCA_FW_INDEV-1]) { - struct rtattr *idev = tb[TCA_FW_INDEV-1]; - if (RTA_PAYLOAD(idev) >= IFNAMSIZ) { - printk("cls_fw: bad indev name %s\n",(char*)RTA_DATA(idev)); - err = -EINVAL; - goto errout; - } - memset(f->indev,0,IFNAMSIZ); - sprintf(f->indev, "%s", (char*)RTA_DATA(idev)); - } -#endif -#else -#ifdef CONFIG_NET_CLS_POLICE - if (tb[TCA_FW_POLICE-1]) - f->police = tcf_police_locate(tb[TCA_FW_POLICE-1], tca[TCA_RATE-1]); -#endif -#endif + err = fw_change_attrs(tp, f, tb, tca, base); + if (err < 0) + goto errout; f->next = head->ht[fw_hash(handle)]; tcf_tree_lock(tp); @@ -419,7 +338,7 @@ static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg) } if (arg->fn(tp, (unsigned long)f, arg) < 0) { arg->stop = 1; - break; + return; } arg->count++; } @@ -438,15 +357,15 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh, t->tcm_handle = f->id; - if (!f->res.classid + if (!f->res.classid #ifdef CONFIG_NET_CLS_ACT - && !f->action + && !f->action #else #ifdef CONFIG_NET_CLS_POLICE - && !f->police + && !f->police #endif #endif - ) + ) return skb->len; rta = (struct rtattr*)b; @@ -454,65 +373,35 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh, if (f->res.classid) RTA_PUT(skb, TCA_FW_CLASSID, 4, &f->res.classid); -#ifdef CONFIG_NET_CLS_ACT - /* again for backward compatible mode - we want - * to work with both old and new modes of entering - * tc data even if iproute2 was newer - jhs - */ - if (f->action) { - struct rtattr * p_rta = (struct rtattr*)skb->tail; - - if (f->action->type != TCA_OLD_COMPAT) { - RTA_PUT(skb, TCA_FW_ACT, 0, NULL); - if (tcf_action_dump(skb,f->action,0,0) < 0) { - goto rtattr_failure; - } - } else { - RTA_PUT(skb, TCA_FW_POLICE, 0, NULL); - if (tcf_action_dump_old(skb,f->action,0,0) < 0) { - goto rtattr_failure; - } - } - - p_rta->rta_len = skb->tail - (u8*)p_rta; - } #ifdef CONFIG_NET_CLS_IND - if(strlen(f->indev)) { - struct rtattr * p_rta = (struct rtattr*)skb->tail; + if (strlen(f->indev)) RTA_PUT(skb, TCA_FW_INDEV, IFNAMSIZ, f->indev); - p_rta->rta_len = skb->tail - (u8*)p_rta; - } -#endif -#else +#endif /* CONFIG_NET_CLS_IND */ +#ifdef CONFIG_NET_CLS_ACT + if (tcf_dump_act(skb, f->action, TCA_FW_ACT, TCA_FW_POLICE) < 0) + goto rtattr_failure; +#else /* CONFIG_NET_CLS_ACT */ #ifdef CONFIG_NET_CLS_POLICE - if (f->police) { - struct rtattr * p_rta = (struct rtattr*)skb->tail; - - RTA_PUT(skb, TCA_FW_POLICE, 0, NULL); - - if (tcf_police_dump(skb, f->police) < 0) - goto rtattr_failure; - - p_rta->rta_len = skb->tail - (u8*)p_rta; - } -#endif -#endif + if (tcf_dump_police(skb, f->police, TCA_FW_POLICE) < 0) + goto rtattr_failure; +#endif /* CONFIG_NET_CLS_POLICE */ +#endif /* CONFIG_NET_CLS_ACT */ rta->rta_len = skb->tail - b; #ifdef CONFIG_NET_CLS_ACT - if (f->action && f->action->type == TCA_OLD_COMPAT) { - if (tcf_action_copy_stats(skb,f->action)) - goto rtattr_failure; - } -#else + if (f->action && f->action->type == TCA_OLD_COMPAT) { + if (tcf_action_copy_stats(skb,f->action)) + goto rtattr_failure; + } +#else /* CONFIG_NET_CLS_ACT */ #ifdef CONFIG_NET_CLS_POLICE if (f->police) { if (qdisc_copy_stats(skb, &f->police->stats, - f->police->stats_lock)) + f->police->stats_lock)) goto rtattr_failure; } -#endif -#endif +#endif /* CONFIG_NET_CLS_POLICE */ +#endif /* CONFIG_NET_CLS_ACT */ return skb->len; rtattr_failure: diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index a39e85264276..f595415d0bac 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c @@ -292,11 +292,8 @@ static void route4_destroy(struct tcf_proto *tp) struct route4_filter *f; while ((f = b->ht[h2]) != NULL) { - unsigned long cl; - b->ht[h2] = f->next; - if ((cl = __cls_set_class(&f->res.class, 0)) != 0) - tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); + tcf_unbind_filter(tp, &f->res); #ifdef CONFIG_NET_CLS_POLICE tcf_police_release(f->police,TCA_ACT_UNBIND); #endif @@ -325,17 +322,12 @@ static int route4_delete(struct tcf_proto *tp, unsigned long arg) for (fp = &b->ht[from_hash(h>>16)]; *fp; fp = &(*fp)->next) { if (*fp == f) { - unsigned long cl; - tcf_tree_lock(tp); *fp = f->next; tcf_tree_unlock(tp); route4_reset_fastmap(tp->q->dev, head, f->id); - - if ((cl = cls_set_class(tp, &f->res.class, 0)) != 0) - tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); - + tcf_unbind_filter(tp, &f->res); #ifdef CONFIG_NET_CLS_POLICE tcf_police_release(f->police,TCA_ACT_UNBIND); #endif @@ -379,27 +371,18 @@ static int route4_change(struct tcf_proto *tp, unsigned long base, return -EINVAL; if ((f = (struct route4_filter*)*arg) != NULL) { - /* Node exists: adjust only classid */ - if (f->handle != handle && handle) return -EINVAL; if (tb[TCA_ROUTE4_CLASSID-1]) { - unsigned long cl; - f->res.classid = *(u32*)RTA_DATA(tb[TCA_ROUTE4_CLASSID-1]); - cl = cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid)); - if (cl) - tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); + tcf_bind_filter(tp, &f->res, base); } #ifdef CONFIG_NET_CLS_POLICE if (tb[TCA_ROUTE4_POLICE-1]) { - struct tcf_police *police = tcf_police_locate(tb[TCA_ROUTE4_POLICE-1], tca[TCA_RATE-1]); - - tcf_tree_lock(tp); - police = xchg(&f->police, police); - tcf_tree_unlock(tp); - - tcf_police_release(police,TCA_ACT_UNBIND); + err = tcf_change_police(tp, &f->police, + tb[TCA_ROUTE4_POLICE-1], tca[TCA_RATE-1]); + if (err < 0) + return err; } #endif return 0; @@ -492,10 +475,10 @@ static int route4_change(struct tcf_proto *tp, unsigned long base, goto errout; } - cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid)); + tcf_bind_filter(tp, &f->res, base); #ifdef CONFIG_NET_CLS_POLICE if (tb[TCA_ROUTE4_POLICE-1]) - f->police = tcf_police_locate(tb[TCA_ROUTE4_POLICE-1], tca[TCA_RATE-1]); + tcf_change_police(tp, &f->police, tb[TCA_ROUTE4_POLICE-1], tca[TCA_RATE-1]); #endif f->next = f1; @@ -538,7 +521,7 @@ static void route4_walk(struct tcf_proto *tp, struct tcf_walker *arg) } if (arg->fn(tp, (unsigned long)f, arg) < 0) { arg->stop = 1; - break; + return; } arg->count++; } @@ -577,16 +560,8 @@ static int route4_dump(struct tcf_proto *tp, unsigned long fh, if (f->res.classid) RTA_PUT(skb, TCA_ROUTE4_CLASSID, 4, &f->res.classid); #ifdef CONFIG_NET_CLS_POLICE - if (f->police) { - struct rtattr * p_rta = (struct rtattr*)skb->tail; - - RTA_PUT(skb, TCA_ROUTE4_POLICE, 0, NULL); - - if (tcf_police_dump(skb, f->police) < 0) - goto rtattr_failure; - - p_rta->rta_len = skb->tail - (u8*)p_rta; - } + if (tcf_dump_police(skb, f->police, TCA_ROUTE4_POLICE) < 0) + goto rtattr_failure; #endif rta->rta_len = skb->tail - b; diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h index f70fad175a6f..7e11260b6930 100644 --- a/net/sched/cls_rsvp.h +++ b/net/sched/cls_rsvp.h @@ -272,11 +272,8 @@ static void rsvp_destroy(struct tcf_proto *tp) struct rsvp_filter *f; while ((f = s->ht[h2]) != NULL) { - unsigned long cl; - s->ht[h2] = f->next; - if ((cl = __cls_set_class(&f->res.class, 0)) != 0) - tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); + tcf_unbind_filter(tp, &f->res); #ifdef CONFIG_NET_CLS_POLICE tcf_police_release(f->police,TCA_ACT_UNBIND); #endif @@ -299,16 +296,10 @@ static int rsvp_delete(struct tcf_proto *tp, unsigned long arg) for (fp = &s->ht[(h>>8)&0xFF]; *fp; fp = &(*fp)->next) { if (*fp == f) { - unsigned long cl; - - tcf_tree_lock(tp); *fp = f->next; tcf_tree_unlock(tp); - - if ((cl = cls_set_class(tp, &f->res.class, 0)) != 0) - tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); - + tcf_unbind_filter(tp, &f->res); #ifdef CONFIG_NET_CLS_POLICE tcf_police_release(f->police,TCA_ACT_UNBIND); #endif @@ -437,22 +428,15 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base, if (f->handle != handle && handle) return -EINVAL; if (tb[TCA_RSVP_CLASSID-1]) { - unsigned long cl; - f->res.classid = *(u32*)RTA_DATA(tb[TCA_RSVP_CLASSID-1]); - cl = cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid)); - if (cl) - tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); + tcf_bind_filter(tp, &f->res, base); } #ifdef CONFIG_NET_CLS_POLICE if (tb[TCA_RSVP_POLICE-1]) { - struct tcf_police *police = tcf_police_locate(tb[TCA_RSVP_POLICE-1], tca[TCA_RATE-1]); - - tcf_tree_lock(tp); - police = xchg(&f->police, police); - tcf_tree_unlock(tp); - - tcf_police_release(police,TCA_ACT_UNBIND); + err = tcf_change_police(tp, &f->police, + tb[TCA_RSVP_POLICE-1], tca[TCA_RATE-1]); + if (err < 0) + return err; } #endif return 0; @@ -531,10 +515,10 @@ insert: f->sess = s; if (f->tunnelhdr == 0) - cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid)); + tcf_bind_filter(tp, &f->res, base); #ifdef CONFIG_NET_CLS_POLICE if (tb[TCA_RSVP_POLICE-1]) - f->police = tcf_police_locate(tb[TCA_RSVP_POLICE-1], tca[TCA_RATE-1]); + tcf_change_police(tp, &f->police, tb[TCA_RSVP_POLICE-1], tca[TCA_RATE-1]); #endif for (fp = &s->ht[h2]; *fp; fp = &(*fp)->next) @@ -601,7 +585,7 @@ static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg) } if (arg->fn(tp, (unsigned long)f, arg) < 0) { arg->stop = 1; - break; + return; } arg->count++; } @@ -641,16 +625,8 @@ static int rsvp_dump(struct tcf_proto *tp, unsigned long fh, if (((f->handle>>8)&0xFF) != 16) RTA_PUT(skb, TCA_RSVP_SRC, sizeof(f->src), f->src); #ifdef CONFIG_NET_CLS_POLICE - if (f->police) { - struct rtattr * p_rta = (struct rtattr*)skb->tail; - - RTA_PUT(skb, TCA_RSVP_POLICE, 0, NULL); - - if (tcf_police_dump(skb, f->police) < 0) - goto rtattr_failure; - - p_rta->rta_len = skb->tail - (u8*)p_rta; - } + if (tcf_dump_police(skb, f->police, TCA_RSVP_POLICE) < 0) + goto rtattr_failure; #endif rta->rta_len = skb->tail - b; diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index f8c58fb573ce..709cf821252a 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c @@ -165,7 +165,6 @@ static int tcindex_delete(struct tcf_proto *tp, unsigned long arg) struct tcindex_data *p = PRIV(tp); struct tcindex_filter_result *r = (struct tcindex_filter_result *) arg; struct tcindex_filter *f = NULL; - unsigned long cl; DPRINTK("tcindex_delete(tp %p,arg 0x%lx),p %p,f %p\n",tp,arg,p,f); if (p->perfect) { @@ -187,9 +186,7 @@ found: *walk = f->next; tcf_tree_unlock(tp); } - cl = __cls_set_class(&r->res.class,0); - if (cl) - tp->q->ops->cl_ops->unbind_tcf(tp->q,cl); + tcf_unbind_filter(tp, &r->res); #ifdef CONFIG_NET_CLS_POLICE tcf_police_release(r->police, TCA_ACT_UNBIND); #endif @@ -313,28 +310,19 @@ static int tcindex_change(struct tcf_proto *tp,unsigned long base,u32 handle, } DPRINTK("r=%p\n",r); if (tb[TCA_TCINDEX_CLASSID-1]) { - unsigned long cl = cls_set_class(tp,&r->res.class,0); - - if (cl) - tp->q->ops->cl_ops->unbind_tcf(tp->q,cl); r->res.classid = *(__u32 *) RTA_DATA(tb[TCA_TCINDEX_CLASSID-1]); - r->res.class = tp->q->ops->cl_ops->bind_tcf(tp->q,base, - r->res.classid); + tcf_bind_filter(tp, &r->res, base); + if (!r->res.class) { r->res.classid = 0; return -ENOENT; } - } + } #ifdef CONFIG_NET_CLS_POLICE - { - struct tcf_police *police; - - police = tb[TCA_TCINDEX_POLICE-1] ? - tcf_police_locate(tb[TCA_TCINDEX_POLICE-1],NULL) : NULL; - tcf_tree_lock(tp); - police = xchg(&r->police,police); - tcf_tree_unlock(tp); - tcf_police_release(police,TCA_ACT_UNBIND); + if (tb[TCA_TCINDEX_POLICE-1]) { + int err = tcf_change_police(tp, &r->police, tb[TCA_TCINDEX_POLICE-1], NULL); + if (err < 0) + return err; } #endif if (r != &new_filter_result) @@ -459,14 +447,8 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh, if (r->res.class) RTA_PUT(skb, TCA_TCINDEX_CLASSID, 4, &r->res.classid); #ifdef CONFIG_NET_CLS_POLICE - if (r->police) { - struct rtattr *p_rta = (struct rtattr *) skb->tail; - - RTA_PUT(skb,TCA_TCINDEX_POLICE,0,NULL); - if (tcf_police_dump(skb,r->police) < 0) - goto rtattr_failure; - p_rta->rta_len = skb->tail-(u8 *) p_rta; - } + if (tcf_dump_police(skb, r->police, TCA_TCINDEX_POLICE) < 0) + goto rtattr_failure; #endif } rta->rta_len = skb->tail-b; diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index c8e11345f308..71330bb41619 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -156,18 +156,9 @@ check_terminal: *res = n->res; #ifdef CONFIG_NET_CLS_IND - /* yes, i know it sucks but the feature is - ** optional dammit! - JHS */ - if (0 != n->indev[0]) { - if (NULL == skb->input_dev) { - n = n->next; - goto next_knode; - } else { - if (0 != strcmp(n->indev, skb->input_dev->name)) { - n = n->next; - goto next_knode; - } - } + if (!tcf_match_indev(skb, n->indev)) { + n = n->next; + goto next_knode; } #endif #ifdef CONFIG_CLS_U32_PERF @@ -346,10 +337,7 @@ static int u32_init(struct tcf_proto *tp) static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n) { - unsigned long cl; - - if ((cl = __cls_set_class(&n->res.class, 0)) != 0) - tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); + tcf_unbind_filter(tp, &n->res); #ifdef CONFIG_NET_CLS_ACT if (n->action) { tcf_action_destroy(n->action, TCA_ACT_UNBIND); @@ -495,15 +483,11 @@ static u32 gen_new_kid(struct tc_u_hnode *ht, u32 handle) return handle|(i>0xFFF ? 0xFFF : i); } -static int u32_set_parms(struct Qdisc *q, unsigned long base, +static int u32_set_parms(struct tcf_proto *tp, unsigned long base, struct tc_u_hnode *ht, struct tc_u_knode *n, struct rtattr **tb, struct rtattr *est) { -#ifdef CONFIG_NET_CLS_ACT - struct tc_action *act = NULL; - int ret; -#endif if (tb[TCA_U32_LINK-1]) { u32 handle = *(u32*)RTA_DATA(tb[TCA_U32_LINK-1]); struct tc_u_hnode *ht_down = NULL; @@ -519,88 +503,43 @@ static int u32_set_parms(struct Qdisc *q, unsigned long base, ht_down->refcnt++; } - sch_tree_lock(q); + tcf_tree_lock(tp); ht_down = xchg(&n->ht_down, ht_down); - sch_tree_unlock(q); + tcf_tree_unlock(tp); if (ht_down) ht_down->refcnt--; } if (tb[TCA_U32_CLASSID-1]) { - unsigned long cl; - n->res.classid = *(u32*)RTA_DATA(tb[TCA_U32_CLASSID-1]); - sch_tree_lock(q); - cl = __cls_set_class(&n->res.class, q->ops->cl_ops->bind_tcf(q, base, n->res.classid)); - sch_tree_unlock(q); - if (cl) - q->ops->cl_ops->unbind_tcf(q, cl); + tcf_bind_filter(tp, &n->res, base); } #ifdef CONFIG_NET_CLS_ACT - /*backward compatibility */ - if (tb[TCA_U32_POLICE-1]) - { - act = kmalloc(sizeof(*act),GFP_KERNEL); - if (NULL == act) - return -ENOMEM; - - memset(act,0,sizeof(*act)); - ret = tcf_action_init_1(tb[TCA_U32_POLICE-1], est,act,"police", TCA_ACT_NOREPLACE, TCA_ACT_BIND); - if (0 > ret){ - tcf_action_destroy(act, TCA_ACT_UNBIND); - return ret; - } - act->type = TCA_OLD_COMPAT; - - sch_tree_lock(q); - act = xchg(&n->action, act); - sch_tree_unlock(q); - - tcf_action_destroy(act, TCA_ACT_UNBIND); - + if (tb[TCA_U32_POLICE-1]) { + int err = tcf_change_act_police(tp, &n->action, tb[TCA_U32_POLICE-1], est); + if (err < 0) + return err; } - if(tb[TCA_U32_ACT-1]) { - act = kmalloc(sizeof(*act),GFP_KERNEL); - if (NULL == act) - return -ENOMEM; - memset(act,0,sizeof(*act)); - ret = tcf_action_init(tb[TCA_U32_ACT-1], est,act,NULL,TCA_ACT_NOREPLACE, TCA_ACT_BIND); - if (0 > ret) { - tcf_action_destroy(act, TCA_ACT_UNBIND); - return ret; - } - - sch_tree_lock(q); - act = xchg(&n->action, act); - sch_tree_unlock(q); - - tcf_action_destroy(act, TCA_ACT_UNBIND); + if (tb[TCA_U32_ACT-1]) { + int err = tcf_change_act(tp, &n->action, tb[TCA_U32_ACT-1], est); + if (err < 0) + return err; } - - #else #ifdef CONFIG_NET_CLS_POLICE if (tb[TCA_U32_POLICE-1]) { - struct tcf_police *police = tcf_police_locate(tb[TCA_U32_POLICE-1], est); - sch_tree_lock(q); - police = xchg(&n->police, police); - sch_tree_unlock(q); - tcf_police_release(police, TCA_ACT_UNBIND); + int err = tcf_change_police(tp, &n->police, tb[TCA_U32_POLICE-1], est); + if (err < 0) + return err; } #endif #endif #ifdef CONFIG_NET_CLS_IND - n->indev[0] = 0; - if(tb[TCA_U32_INDEV-1]) { - struct rtattr *input_dev = tb[TCA_U32_INDEV-1]; - if (RTA_PAYLOAD(input_dev) >= IFNAMSIZ) { - printk("cls_u32: bad indev name %s\n",(char*)RTA_DATA(input_dev)); - /* should we clear state first? */ - return -EINVAL; - } - sprintf(n->indev, "%s", (char*)RTA_DATA(input_dev)); - printk("got IND %s\n",n->indev); + if (tb[TCA_U32_INDEV-1]) { + int err = tcf_change_indev(tp, n->indev, tb[TCA_U32_INDEV-1]); + if (err < 0) + return err; } #endif @@ -630,7 +569,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, if (TC_U32_KEY(n->handle) == 0) return -EINVAL; - return u32_set_parms(tp->q, base, n->ht_up, n, tb, tca[TCA_RATE-1]); + return u32_set_parms(tp, base, n->ht_up, n, tb, tca[TCA_RATE-1]); } if (tb[TCA_U32_DIVISOR-1]) { @@ -718,7 +657,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, } n->fshift = i; } - err = u32_set_parms(tp->q, base, ht, n, tb, tca[TCA_RATE-1]); + err = u32_set_parms(tp, base, ht, n, tb, tca[TCA_RATE-1]); if (err == 0) { struct tc_u_knode **ins; for (ins = &ht->ht[TC_U32_HASH(handle)]; *ins; ins = &(*ins)->next) @@ -806,49 +745,18 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh, if (n->ht_down) RTA_PUT(skb, TCA_U32_LINK, 4, &n->ht_down->handle); #ifdef CONFIG_NET_CLS_ACT - /* again for backward compatible mode - we want - * to work with both old and new modes of entering - * tc data even if iproute2 was newer - jhs - */ - if (n->action) { - struct rtattr * p_rta = (struct rtattr*)skb->tail; - - if (n->action->type != TCA_OLD_COMPAT) { - RTA_PUT(skb, TCA_U32_ACT, 0, NULL); - if (tcf_action_dump(skb,n->action, 0, 0) < 0) { - goto rtattr_failure; - } - } else { - RTA_PUT(skb, TCA_U32_POLICE, 0, NULL); - if (tcf_action_dump_old(skb,n->action,0,0) < 0) { - goto rtattr_failure; - } - } - - p_rta->rta_len = skb->tail - (u8*)p_rta; - } - + if (tcf_dump_act(skb, n->action, TCA_U32_ACT, TCA_U32_POLICE) < 0) + goto rtattr_failure; #else #ifdef CONFIG_NET_CLS_POLICE - if (n->police) { - struct rtattr * p_rta = (struct rtattr*)skb->tail; - RTA_PUT(skb, TCA_U32_POLICE, 0, NULL); - - if (tcf_police_dump(skb, n->police) < 0) - goto rtattr_failure; - - p_rta->rta_len = skb->tail - (u8*)p_rta; - - } + if (tcf_dump_police(skb, n->police, TCA_U32_POLICE) < 0) + goto rtattr_failure; #endif #endif #ifdef CONFIG_NET_CLS_IND - if(strlen(n->indev)) { - struct rtattr * p_rta = (struct rtattr*)skb->tail; + if(strlen(n->indev)) RTA_PUT(skb, TCA_U32_INDEV, IFNAMSIZ, n->indev); - p_rta->rta_len = skb->tail - (u8*)p_rta; - } #endif #ifdef CONFIG_CLS_U32_PERF RTA_PUT(skb, TCA_U32_PCNT, diff --git a/net/sched/ipt.c b/net/sched/ipt.c new file mode 100644 index 000000000000..4938cd95e693 --- /dev/null +++ b/net/sched/ipt.c @@ -0,0 +1,392 @@ +/* + * net/sched/ipt.c iptables target interface + * + *TODO: Add other tables. For now we only support the ipv4 table targets + * + * 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. + * + * Copyright: Jamal Hadi Salim (2002-4) + */ + +#include <asm/uaccess.h> +#include <asm/system.h> +#include <asm/bitops.h> +#include <linux/config.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/socket.h> +#include <linux/sockios.h> +#include <linux/in.h> +#include <linux/errno.h> +#include <linux/interrupt.h> +#include <linux/netdevice.h> +#include <linux/skbuff.h> +#include <linux/rtnetlink.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/proc_fs.h> +#include <net/sock.h> +#include <net/pkt_sched.h> +#include <linux/tc_act/tc_ipt.h> +#include <net/tc_act/tc_ipt.h> + +#include <linux/netfilter_ipv4/ip_tables.h> + +/* use generic hash table */ +#define MY_TAB_SIZE 16 +#define MY_TAB_MASK 15 + +u32 idx_gen; +static struct tcf_ipt *tcf_ipt_ht[MY_TAB_SIZE]; +/* ipt hash table lock */ +static rwlock_t ipt_lock = RW_LOCK_UNLOCKED; + +/* ovewrride the defaults */ +#define tcf_st tcf_ipt +#define tcf_t_lock ipt_lock +#define tcf_ht tcf_ipt_ht + +#include <net/pkt_act.h> + +static inline int +init_targ(struct tcf_ipt *p) +{ + struct ipt_target *target; + int ret = 0; + struct ipt_entry_target *t = p->t; + target = __ipt_find_target_lock(t->u.user.name, &ret); + + if (!target) { + printk("init_targ: Failed to find %s\n", + t->u.kernel.target->name); + return -1; + } + + DPRINTK("init_targ: found %s\n", target->name); + /* we really need proper ref counting + seems to be only needed for modules?? Talk to laforge */ +/* if (target->me) + __MOD_INC_USE_COUNT(target->me); +*/ + t->u.kernel.target = target; + + __ipt_mutex_up(); + + if (t->u.kernel.target->checkentry + && !t->u.kernel.target->checkentry(p->tname, NULL, t->data, + t->u.target_size + - sizeof (*t), p->hook)) { +/* if (t->u.kernel.target->me) + __MOD_DEC_USE_COUNT(t->u.kernel.target->me); +*/ + DPRINTK("ip_tables: check failed for `%s'.\n", + t->u.kernel.target->name); + ret = -EINVAL; + } + + return ret; +} + +int +tcf_ipt_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, int ovr, int bind) +{ + struct ipt_entry_target *t; + unsigned h; + struct rtattr *tb[TCA_IPT_MAX]; + struct tcf_ipt *p; + int ret = 0; + u32 index = 0; + u32 hook = 0; + + if (NULL == a || NULL == rta || + (rtattr_parse(tb, TCA_IPT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < + 0)) { + return -1; + } + + + if (tb[TCA_IPT_INDEX - 1]) { + index = *(u32 *) RTA_DATA(tb[TCA_IPT_INDEX - 1]); + DPRINTK("ipt index %d\n", index); + } + + if (index && (p = tcf_hash_lookup(index)) != NULL) { + a->priv = (void *) p; + spin_lock(&p->lock); + if (bind) { + p->bindcnt += 1; + p->refcnt += 1; + } + if (ovr) { + goto override; + } + spin_unlock(&p->lock); + return ret; + } + + if (NULL == tb[TCA_IPT_TARG - 1] || NULL == tb[TCA_IPT_HOOK - 1]) { + return -1; + } + + p = kmalloc(sizeof (*p), GFP_KERNEL); + if (p == NULL) + return -1; + + memset(p, 0, sizeof (*p)); + p->refcnt = 1; + ret = 1; + spin_lock_init(&p->lock); + p->stats_lock = &p->lock; + if (bind) + p->bindcnt = 1; + +override: + hook = *(u32 *) RTA_DATA(tb[TCA_IPT_HOOK - 1]); + + t = (struct ipt_entry_target *) RTA_DATA(tb[TCA_IPT_TARG - 1]); + + p->t = kmalloc(t->u.target_size, GFP_KERNEL); + if (p->t == NULL) { + if (ovr) { + printk("ipt policy messed up \n"); + spin_unlock(&p->lock); + return -1; + } + kfree(p); + return -1; + } + + memcpy(p->t, RTA_DATA(tb[TCA_IPT_TARG - 1]), t->u.target_size); + DPRINTK(" target NAME %s size %d data[0] %x data[1] %x\n", + t->u.user.name, t->u.target_size, t->data[0], t->data[1]); + + p->tname = kmalloc(IFNAMSIZ, GFP_KERNEL); + + if (p->tname == NULL) { + if (ovr) { + printk("ipt policy messed up 2 \n"); + spin_unlock(&p->lock); + return -1; + } + kfree(p->t); + kfree(p); + return -1; + } else { + int csize = IFNAMSIZ - 1; + + memset(p->tname, 0, IFNAMSIZ); + if (tb[TCA_IPT_TABLE - 1]) { + if (strlen((char *) RTA_DATA(tb[TCA_IPT_TABLE - 1])) < + csize) + csize = strlen(RTA_DATA(tb[TCA_IPT_TABLE - 1])); + strncpy(p->tname, RTA_DATA(tb[TCA_IPT_TABLE - 1]), + csize); + DPRINTK("table name %s\n", p->tname); + } else { + strncpy(p->tname, "mangle", 1 + strlen("mangle")); + } + } + + if (0 > init_targ(p)) { + if (ovr) { + printk("ipt policy messed up 2 \n"); + spin_unlock(&p->lock); + return -1; + } + kfree(p->tname); + kfree(p->t); + kfree(p); + return -1; + } + + if (ovr) { + spin_unlock(&p->lock); + return -1; + } + + p->index = index ? : tcf_hash_new_index(); + + p->tm.lastuse = jiffies; + /* + p->tm.expires = jiffies; + */ + p->tm.install = jiffies; +#ifdef CONFIG_NET_ESTIMATOR + if (est) { + qdisc_new_estimator(&p->stats, p->stats_lock, est); + } +#endif + h = tcf_hash(p->index); + write_lock_bh(&ipt_lock); + p->next = tcf_ipt_ht[h]; + tcf_ipt_ht[h] = p; + write_unlock_bh(&ipt_lock); + a->priv = (void *) p; + return ret; + +} + +int +tcf_ipt_cleanup(struct tc_action *a, int bind) +{ + struct tcf_ipt *p; + p = PRIV(a,ipt); + if (NULL != p) + return tcf_hash_release(p, bind); + return 0; +} + +int +tcf_ipt(struct sk_buff **pskb, struct tc_action *a) +{ + int ret = 0, result = 0; + struct tcf_ipt *p; + struct sk_buff *skb = *pskb; + + p = PRIV(a,ipt); + + if (NULL == p || NULL == skb) { + return -1; + } + + spin_lock(&p->lock); + + p->tm.lastuse = jiffies; + p->stats.bytes += skb->len; + p->stats.packets++; + + if (skb_cloned(skb) ) { + if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { + return -1; + } + } + /* yes, we have to worry about both in and out dev + worry later - danger - this API seems to have changed + from earlier kernels */ + + ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL, + p->hook, p->t->data, (void *)NULL); + switch (ret) { + case NF_ACCEPT: + result = TC_ACT_OK; + break; + case NF_DROP: + result = TC_ACT_SHOT; + p->stats.drops++; + break; + case IPT_CONTINUE: + result = TC_ACT_PIPE; + break; + default: + if (net_ratelimit()) + printk("Bogus netfilter code %d assume ACCEPT\n", ret); + result = TC_POLICE_OK; + break; + } + spin_unlock(&p->lock); + return result; + +} + +int +tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) +{ + struct ipt_entry_target *t; + struct tcf_t tm; + struct tc_cnt c; + unsigned char *b = skb->tail; + + struct tcf_ipt *p; + + p = PRIV(a,ipt); + if (NULL == p) { + printk("BUG: tcf_ipt_dump called with NULL params\n"); + goto rtattr_failure; + } + /* for simple targets kernel size == user size + ** user name = target name + ** for foolproof you need to not assume this + */ + + t = kmalloc(p->t->u.user.target_size, GFP_ATOMIC); + + if (NULL == t) + goto rtattr_failure; + + c.bindcnt = p->bindcnt - bind; + c.refcnt = p->refcnt - ref; + memcpy(t, p->t, p->t->u.user.target_size); + strcpy(t->u.user.name, p->t->u.kernel.target->name); + + DPRINTK("\ttcf_ipt_dump tablename %s length %d\n", p->tname, + strlen(p->tname)); + DPRINTK + ("\tdump target name %s size %d size user %d data[0] %x data[1] %x\n", + p->t->u.kernel.target->name, p->t->u.target_size, p->t->u.user.target_size, + p->t->data[0], p->t->data[1]); + RTA_PUT(skb, TCA_IPT_TARG, p->t->u.user.target_size, t); + RTA_PUT(skb, TCA_IPT_INDEX, 4, &p->index); + RTA_PUT(skb, TCA_IPT_HOOK, 4, &p->hook); + RTA_PUT(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c); + RTA_PUT(skb, TCA_IPT_TABLE, IFNAMSIZ, p->tname); + tm.install = jiffies - p->tm.install; + tm.lastuse = jiffies - p->tm.lastuse; + tm.expires = p->tm.expires; + RTA_PUT(skb, TCA_IPT_TM, sizeof (tm), &tm); + return skb->len; + + rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; +} + +int +tcf_ipt_stats(struct sk_buff *skb, struct tc_action *a) +{ + struct tcf_ipt *p; + p = PRIV(a,ipt); + if (NULL != p) + return qdisc_copy_stats(skb, &p->stats, p->stats_lock); + + return 1; +} + +struct tc_action_ops act_ipt_ops = { + .next = NULL, + .kind = "ipt", + .type = TCA_ACT_IPT, + .capab = TCA_CAP_NONE, + .owner = THIS_MODULE, + .act = tcf_ipt, + .get_stats = tcf_ipt_stats, + .dump = tcf_ipt_dump, + .cleanup = tcf_ipt_cleanup, + .lookup = tcf_hash_search, + .init = tcf_ipt_init, + .walk = tcf_generic_walker +}; + +MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); +MODULE_DESCRIPTION("Iptables target actions"); +MODULE_LICENSE("GPL"); + +static int __init +ipt_init_module(void) +{ + return tcf_register_action(&act_ipt_ops); +} + +static void __exit +ipt_cleanup_module(void) +{ + tcf_unregister_action(&act_ipt_ops); +} + +module_init(ipt_init_module); +module_exit(ipt_cleanup_module); diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 8f2d18263792..36ddfb78d41e 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -98,16 +98,6 @@ static inline void sctp_outq_tail_data(struct sctp_outq *q, return; } -/* Insert a chunk behind chunk 'pos'. */ -static inline void sctp_outq_insert_data(struct sctp_outq *q, - struct sctp_chunk *ch, - struct sctp_chunk *pos) -{ - __skb_insert((struct sk_buff *)ch, (struct sk_buff *)pos->prev, - (struct sk_buff *)pos, pos->list); - q->out_qlen += ch->skb->len; -} - /* * SFR-CACC algorithm: * D) If count_of_newacks is greater than or equal to 2 diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index be33fd881a74..2d8ee7ce0d8f 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -347,6 +347,7 @@ void x25_destroy_socket(struct sock *sk) /* Defer: outstanding buffers */ sk->sk_timer.expires = jiffies + 10 * HZ; sk->sk_timer.function = x25_destroy_timer; + sk->sk_timer.data = (unsigned long)sk; add_timer(&sk->sk_timer); } else { /* drop last reference so sock_put will free */ diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c index f58aa65ea965..99af8425fbfc 100644 --- a/net/x25/x25_dev.c +++ b/net/x25/x25_dev.c @@ -92,7 +92,9 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *nb) /* x25_transmit_clear_request(nb, lci, 0x0D); */ - printk(KERN_DEBUG "x25_receive_data(): unknown frame type %2x\n",frametype); + + if (frametype != X25_CLEAR_CONFIRMATION) + printk(KERN_DEBUG "x25_receive_data(): unknown frame type %2x\n",frametype); return 0; } diff --git a/net/x25/x25_proc.c b/net/x25/x25_proc.c index ef3140d1041b..64fff05abf8a 100644 --- a/net/x25/x25_proc.c +++ b/net/x25/x25_proc.c @@ -32,10 +32,11 @@ static __inline__ struct x25_route *x25_get_route_idx(loff_t pos) list_for_each(route_entry, &x25_route_list) { rt = list_entry(route_entry, struct x25_route, node); - if (--pos) - break; + if (!pos--) + goto found; } - + rt = NULL; +found: return rt; } diff --git a/net/xfrm/Kconfig b/net/xfrm/Kconfig index 58c7d2671389..58ca6a972c48 100644 --- a/net/xfrm/Kconfig +++ b/net/xfrm/Kconfig @@ -1,10 +1,6 @@ # # XFRM configuration # -config XFRM - bool - depends on NET - config XFRM_USER tristate "IPsec user configuration interface" depends on INET && XFRM diff --git a/net/xfrm/xfrm_export.c b/net/xfrm/xfrm_export.c index 24dbc9a99b1b..fd34836cdf7f 100644 --- a/net/xfrm/xfrm_export.c +++ b/net/xfrm/xfrm_export.c @@ -27,7 +27,6 @@ EXPORT_SYMBOL(__secpath_destroy); EXPORT_SYMBOL(secpath_dup); EXPORT_SYMBOL(xfrm_get_acqseq); EXPORT_SYMBOL(xfrm_parse_spi); -EXPORT_SYMBOL(xfrm4_rcv); EXPORT_SYMBOL(xfrm_register_type); EXPORT_SYMBOL(xfrm_unregister_type); EXPORT_SYMBOL(xfrm_get_type); |
