Commit 48e24acb authored by David S. Miller's avatar David S. Miller

Merge davem@nuts.davemloft.net:/disk1/BK/net-2.6

into kernel.bkbits.net:/home/davem/net-2.6
parents 0092e993 4f6aeb92
#ifndef _IP6T_REJECT_H
#define _IP6T_REJECT_H
enum ip6t_reject_with {
IP6T_ICMP_NET_UNREACHABLE,
IP6T_ICMP_HOST_UNREACHABLE,
IP6T_ICMP_PROT_UNREACHABLE,
IP6T_ICMP_PORT_UNREACHABLE,
IP6T_ICMP_ECHOREPLY
};
struct ip6t_reject_info {
enum ip6t_reject_with with; /* reject type */
};
#endif /*_IPT_REJECT_H*/
......@@ -134,13 +134,6 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long t
void netlink_detachskb(struct sock *sk, struct sk_buff *skb);
int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol);
/* finegrained unicast helpers: */
struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid);
struct sock *netlink_getsockbyfilp(struct file *filp);
int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long timeo);
void netlink_detachskb(struct sock *sk, struct sk_buff *skb);
int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol);
/*
* skb should fit one page. This choice is good for headerless malloc.
*
......
......@@ -402,6 +402,16 @@ enum {
#define TCA_ATM_MAX TCA_ATM_STATE
/* Network emulator */
enum
{
TCA_NETEM_UNSPEC,
TCA_NETEM_CORR,
TCA_NETEM_DELAY_DIST,
};
#define TCA_NETEM_MAX TCA_NETEM_DELAY_DIST
struct tc_netem_qopt
{
__u32 latency; /* added delay (us) */
......@@ -411,4 +421,19 @@ struct tc_netem_qopt
__u32 duplicate; /* random packet dup (0=none ~0=100%) */
__u32 jitter; /* random jitter in latency (us) */
};
struct tc_netem_corr
{
__u32 delay_corr; /* delay correlation */
__u32 loss_corr; /* packet loss correlation */
__u32 dup_corr; /* duplicate correlation */
};
struct tc_netem_dist
{
__u32 size; /* table size */
__u32 factor; /* table scaling factor */
__s16 data[0]; /* distribution table values */
};
#endif
......@@ -106,7 +106,7 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
{
char *arpptr = (char *)(arphdr + 1);
char *src_devaddr, *tgt_devaddr;
u32 *src_ipaddr, *tgt_ipaddr;
u32 src_ipaddr, tgt_ipaddr;
int i, ret;
#define FWINV(bool,invflg) ((bool) ^ !!(arpinfo->invflags & invflg))
......@@ -145,11 +145,11 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
src_devaddr = arpptr;
arpptr += dev->addr_len;
src_ipaddr = (u32 *) arpptr;
memcpy(&src_ipaddr, arpptr, sizeof(u32));
arpptr += sizeof(u32);
tgt_devaddr = arpptr;
arpptr += dev->addr_len;
tgt_ipaddr = (u32 *) arpptr;
memcpy(&tgt_ipaddr, arpptr, sizeof(u32));
if (FWINV(arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr, dev->addr_len),
ARPT_INV_SRCDEVADDR) ||
......@@ -160,19 +160,19 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
return 0;
}
if (FWINV(((*src_ipaddr) & arpinfo->smsk.s_addr) != arpinfo->src.s_addr,
if (FWINV((src_ipaddr & arpinfo->smsk.s_addr) != arpinfo->src.s_addr,
ARPT_INV_SRCIP) ||
FWINV((((*tgt_ipaddr) & arpinfo->tmsk.s_addr) != arpinfo->tgt.s_addr),
FWINV(((tgt_ipaddr & arpinfo->tmsk.s_addr) != arpinfo->tgt.s_addr),
ARPT_INV_TGTIP)) {
dprintf("Source or target IP address mismatch.\n");
dprintf("SRC: %u.%u.%u.%u. Mask: %u.%u.%u.%u. Target: %u.%u.%u.%u.%s\n",
NIPQUAD(*src_ipaddr),
NIPQUAD(src_ipaddr),
NIPQUAD(arpinfo->smsk.s_addr),
NIPQUAD(arpinfo->src.s_addr),
arpinfo->invflags & ARPT_INV_SRCIP ? " (INV)" : "");
dprintf("TGT: %u.%u.%u.%u Mask: %u.%u.%u.%u Target: %u.%u.%u.%u.%s\n",
NIPQUAD(*tgt_ipaddr),
NIPQUAD(tgt_ipaddr),
NIPQUAD(arpinfo->tmsk.s_addr),
NIPQUAD(arpinfo->tgt.s_addr),
arpinfo->invflags & ARPT_INV_TGTIP ? " (INV)" : "");
......
......@@ -38,7 +38,7 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
struct inet_opt *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
struct in6_addr *daddr;
struct in6_addr *daddr, *final_p = NULL, final;
struct dst_entry *dst;
struct flowi fl;
struct ip6_flowlabel *flowlabel = NULL;
......@@ -157,16 +157,27 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (flowlabel) {
if (flowlabel->opt && flowlabel->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt;
ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
final_p = &final;
}
} else if (np->opt && np->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
final_p = &final;
}
err = ip6_dst_lookup(sk, &dst, &fl);
if (err)
goto out;
if (final_p)
ipv6_addr_copy(&fl.fl6_dst, final_p);
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
dst_release(dst);
goto out;
}
/* source address lookup done in ip6_dst_lookup */
......
......@@ -796,10 +796,6 @@ int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
goto out_err_release;
}
}
if ((err = xfrm_lookup(dst, fl, sk, 0)) < 0) {
err = -ENETUNREACH;
goto out_err_release;
}
return 0;
......
......@@ -606,7 +606,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
{
struct ipv6_txoptions opt_space;
struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name;
struct in6_addr *daddr;
struct in6_addr *daddr, *final_p = NULL, final;
struct inet_opt *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
struct raw6_opt *raw_opt = raw6_sk(sk);
......@@ -729,7 +729,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
/* merge ip6_build_xmit from ip6_output */
if (opt && opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
final_p = &final;
}
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
......@@ -738,6 +740,13 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
err = ip6_dst_lookup(sk, &dst, &fl);
if (err)
goto out;
if (final_p)
ipv6_addr_copy(&fl.fl6_dst, final_p);
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
dst_release(dst);
goto out;
}
if (hlimit < 0) {
if (ipv6_addr_is_multicast(&fl.fl6_dst))
......
......@@ -549,7 +549,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
struct inet_opt *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
struct tcp_opt *tp = tcp_sk(sk);
struct in6_addr *saddr = NULL;
struct in6_addr *saddr = NULL, *final_p = NULL, final;
struct flowi fl;
struct dst_entry *dst;
int addr_type;
......@@ -666,13 +666,21 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
if (np->opt && np->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
final_p = &final;
}
err = ip6_dst_lookup(sk, &dst, &fl);
if (err)
goto failure;
if (final_p)
ipv6_addr_copy(&fl.fl6_dst, final_p);
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
dst_release(dst);
goto failure;
}
if (saddr == NULL) {
saddr = &fl.fl6_src;
......@@ -793,6 +801,12 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
sk->sk_err_soft = -err;
goto out;
}
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
sk->sk_err_soft = -err;
goto out;
}
} else
dst_hold(dst);
......@@ -863,6 +877,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req,
struct ipv6_pinfo *np = inet6_sk(sk);
struct sk_buff * skb;
struct ipv6_txoptions *opt = NULL;
struct in6_addr * final_p = NULL, final;
struct flowi fl;
int err = -1;
......@@ -888,12 +903,18 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req,
if (opt && opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
final_p = &final;
}
err = ip6_dst_lookup(sk, &dst, &fl);
if (err)
goto done;
if (final_p)
ipv6_addr_copy(&fl.fl6_dst, final_p);
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
goto done;
}
skb = tcp_make_synack(sk, dst, req);
......@@ -1021,6 +1042,12 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
/* sk = NULL, but it is safe for now. RST socket required. */
if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) {
dst_release(buff->dst);
return;
}
ip6_xmit(NULL, buff, &fl, NULL, 0);
TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
......@@ -1082,6 +1109,10 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
fl.fl_ip_sport = t1->source;
if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) {
dst_release(buff->dst);
return;
}
ip6_xmit(NULL, buff, &fl, NULL, 0);
TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
return;
......@@ -1313,6 +1344,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
}
if (dst == NULL) {
struct in6_addr *final_p = NULL, final;
struct flowi fl;
memset(&fl, 0, sizeof(fl));
......@@ -1320,7 +1352,9 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr);
if (opt && opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
final_p = &final;
}
ipv6_addr_copy(&fl.fl6_src, &req->af.v6_req.loc_addr);
fl.oif = sk->sk_bound_dev_if;
......@@ -1329,6 +1363,12 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
if (ip6_dst_lookup(sk, &dst, &fl))
goto out;
if (final_p)
ipv6_addr_copy(&fl.fl6_dst, final_p);
if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0)
goto out;
}
newsk = tcp_create_openreq_child(sk, req, skb);
......@@ -1710,6 +1750,7 @@ static int tcp_v6_rebuild_header(struct sock *sk)
if (dst == NULL) {
struct inet_opt *inet = inet_sk(sk);
struct in6_addr *final_p = NULL, final;
struct flowi fl;
memset(&fl, 0, sizeof(fl));
......@@ -1723,15 +1764,24 @@ static int tcp_v6_rebuild_header(struct sock *sk)
if (np->opt && np->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
final_p = &final;
}
err = ip6_dst_lookup(sk, &dst, &fl);
if (err) {
sk->sk_route_caps = 0;
return err;
}
if (final_p)
ipv6_addr_copy(&fl.fl6_dst, final_p);
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
sk->sk_err_soft = -err;
dst_release(dst);
return err;
}
ip6_dst_store(sk, dst, NULL);
sk->sk_route_caps = dst->dev->features &
......@@ -1775,6 +1825,12 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok)
return err;
}
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
sk->sk_route_caps = 0;
dst_release(dst);
return err;
}
ip6_dst_store(sk, dst, NULL);
sk->sk_route_caps = dst->dev->features &
~(NETIF_F_IP_CSUM | NETIF_F_TSO);
......
......@@ -627,7 +627,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
struct inet_opt *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name;
struct in6_addr *daddr;
struct in6_addr *daddr, *final_p = NULL, final;
struct ipv6_txoptions *opt = NULL;
struct ip6_flowlabel *flowlabel = NULL;
struct flowi *fl = &inet->cork.fl;
......@@ -783,7 +783,9 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
/* merge ip6_build_xmit from ip6_output */
if (opt && opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
ipv6_addr_copy(&final, &fl->fl6_dst);
ipv6_addr_copy(&fl->fl6_dst, rt0->addr);
final_p = &final;
}
if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst))
......@@ -792,6 +794,13 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
err = ip6_dst_lookup(sk, &dst, fl);
if (err)
goto out;
if (final_p)
ipv6_addr_copy(&fl->fl6_dst, final_p);
if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) {
dst_release(dst);
goto out;
}
if (hlimit < 0) {
if (ipv6_addr_is_multicast(&fl->fl6_dst))
......
......@@ -46,6 +46,7 @@
#include <linux/security.h>
#include <net/sock.h>
#include <net/scm.h>
#include <linux/workqueue.h>
#define Nprintk(a...)
......@@ -69,6 +70,14 @@ struct netlink_opt
#define nlk_sk(__sk) ((struct netlink_opt *)(__sk)->sk_protinfo)
struct netlink_work
{
struct sock *sk;
int len;
struct work_struct work;
};
static struct workqueue_struct *netlink_wq;
static struct hlist_head nl_table[MAX_LINKS];
static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait);
static unsigned nl_nonroot[MAX_LINKS];
......@@ -87,6 +96,16 @@ static atomic_t nl_table_users = ATOMIC_INIT(0);
static struct notifier_block *netlink_chain;
/* netlink workqueue handler */
static void netlink_wq_handler(void *data)
{
struct netlink_work *work = data;
work->sk->sk_data_ready(work->sk, work->len);
sock_put(work->sk);
kfree(work);
}
static void netlink_sock_destruct(struct sock *sk)
{
skb_queue_purge(&sk->sk_receive_queue);
......@@ -478,6 +497,8 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long t
if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf ||
test_bit(0, &nlk->state)) {
DECLARE_WAITQUEUE(wait, current);
task_t *client;
if (!timeo) {
if (!nlk->pid)
netlink_overrun(sk);
......@@ -486,6 +507,19 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long t
return -EAGAIN;
}
if (nlk->pid) {
/* Kernel is sending information to user space
* and socket buffer is full: Wake up user
* process */
client = find_task_by_pid(nlk->pid);
if (!client) {
sock_put(sk);
kfree_skb(skb);
return -EAGAIN;
}
wake_up_process(client);
}
__set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&nlk->wait, &wait);
......@@ -525,8 +559,24 @@ int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol)
#endif
skb_queue_tail(&sk->sk_receive_queue, skb);
if (!nlk->pid) {
struct netlink_work *nlwork =
kmalloc(sizeof(struct netlink_work), GFP_KERNEL);
if (!nlwork) {
sock_put(sk);
return -EAGAIN;
}
INIT_WORK(&nlwork->work, netlink_wq_handler, nlwork);
nlwork->sk = sk;
nlwork->len = len;
queue_work(netlink_wq, &nlwork->work);
} else {
sk->sk_data_ready(sk, len);
sock_put(sk);
}
return len;
}
......@@ -573,7 +623,21 @@ static __inline__ int netlink_broadcast_deliver(struct sock *sk, struct sk_buff
skb_orphan(skb);
skb_set_owner_r(skb, sk);
skb_queue_tail(&sk->sk_receive_queue, skb);
if (!nlk->pid) {
struct netlink_work *nlwork =
kmalloc(sizeof(struct netlink_work), GFP_KERNEL);
if (!nlwork)
return -1;
INIT_WORK(&nlwork->work, netlink_wq_handler, nlwork);
nlwork->sk = sk;
nlwork->len = skb->len;
queue_work(netlink_wq, &nlwork->work);
} else
sk->sk_data_ready(sk, skb->len);
return 0;
}
return -1;
......@@ -619,13 +683,14 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
netlink_overrun(sk);
/* Clone failed. Notify ALL listeners. */
failure = 1;
sock_put(sk);
} else if (netlink_broadcast_deliver(sk, skb2)) {
netlink_overrun(sk);
sock_put(sk);
} else {
delivered = 1;
skb2 = NULL;
}
sock_put(sk);
}
netlink_unlock_table();
......@@ -1202,6 +1267,9 @@ static int __init netlink_proto_init(void)
#endif
/* The netlink device handler may be needed early. */
rtnetlink_init();
/* Create a work queue to handle callbacks to modules */
netlink_wq = create_workqueue("netlink");
return 0;
}
......@@ -1209,6 +1277,7 @@ static void __exit netlink_proto_exit(void)
{
sock_unregister(PF_NETLINK);
proc_net_remove("netlink");
destroy_workqueue(netlink_wq);
}
core_initcall(netlink_proto_init);
......
......@@ -66,6 +66,7 @@
#include <asm/uaccess.h>
#include <asm/ioctls.h>
#include <asm/page.h>
#include <asm/io.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/poll.h>
......@@ -173,7 +174,7 @@ struct packet_opt
{
struct tpacket_stats stats;
#ifdef CONFIG_PACKET_MMAP
unsigned long *pg_vec;
char * *pg_vec;
unsigned int head;
unsigned int frames_per_block;
unsigned int frame_size;
......@@ -198,15 +199,15 @@ struct packet_opt
#ifdef CONFIG_PACKET_MMAP
static inline unsigned long packet_lookup_frame(struct packet_opt *po, unsigned int position)
static inline char *packet_lookup_frame(struct packet_opt *po, unsigned int position)
{
unsigned int pg_vec_pos, frame_offset;
unsigned long frame;
char *frame;
pg_vec_pos = position / po->frames_per_block;
frame_offset = position % po->frames_per_block;
frame = (unsigned long) (po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size));
frame = po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size);
return frame;
}
......@@ -1549,7 +1550,12 @@ static struct vm_operations_struct packet_mmap_ops = {
.close =packet_mm_close,
};
static void free_pg_vec(unsigned long *pg_vec, unsigned order, unsigned len)
static inline struct page *pg_vec_endpage(char *one_pg_vec, unsigned int order)
{
return virt_to_page(one_pg_vec + (PAGE_SIZE << order) - 1);
}
static void free_pg_vec(char **pg_vec, unsigned order, unsigned len)
{
int i;
......@@ -1557,10 +1563,10 @@ static void free_pg_vec(unsigned long *pg_vec, unsigned order, unsigned len)
if (pg_vec[i]) {
struct page *page, *pend;
pend = virt_to_page(pg_vec[i] + (PAGE_SIZE << order) - 1);
pend = pg_vec_endpage(pg_vec[i], order);
for (page = virt_to_page(pg_vec[i]); page <= pend; page++)
ClearPageReserved(page);
free_pages(pg_vec[i], order);
free_pages((unsigned long)pg_vec[i], order);
}
}
kfree(pg_vec);
......@@ -1569,7 +1575,7 @@ static void free_pg_vec(unsigned long *pg_vec, unsigned order, unsigned len)
static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing)
{
unsigned long *pg_vec = NULL;
char **pg_vec = NULL;
struct packet_opt *po = pkt_sk(sk);
int was_running, num, order = 0;
int err = 0;
......@@ -1604,18 +1610,18 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing
err = -ENOMEM;
pg_vec = kmalloc(req->tp_block_nr*sizeof(unsigned long*), GFP_KERNEL);
pg_vec = kmalloc(req->tp_block_nr*sizeof(char *), GFP_KERNEL);
if (pg_vec == NULL)
goto out;
memset(pg_vec, 0, req->tp_block_nr*sizeof(unsigned long*));
memset(pg_vec, 0, req->tp_block_nr*sizeof(char **));
for (i=0; i<req->tp_block_nr; i++) {
struct page *page, *pend;
pg_vec[i] = __get_free_pages(GFP_KERNEL, order);
pg_vec[i] = (char *)__get_free_pages(GFP_KERNEL, order);
if (!pg_vec[i])
goto out_free_pgvec;
pend = virt_to_page(pg_vec[i] + (PAGE_SIZE << order) - 1);
pend = pg_vec_endpage(pg_vec[i], order);
for (page = virt_to_page(pg_vec[i]); page <= pend; page++)
SetPageReserved(page);
}
......@@ -1623,7 +1629,7 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing
l = 0;
for (i=0; i<req->tp_block_nr; i++) {
unsigned long ptr = pg_vec[i];
char *ptr = pg_vec[i];
struct tpacket_hdr *header;
int k;
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment