Commit c4331890 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/davem/net-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 20efbf29 6bfeebf2
......@@ -630,19 +630,15 @@ static int __init scc_enet_init(void)
bd = (bd_t *)__res;
/* Allocate some private information.
/* Create an Ethernet device instance.
*/
cep = (struct scc_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
if (cep == NULL)
dev = alloc_etherdev(sizeof(*cep));
if (!dev)
return -ENOMEM;
__clear_user(cep,sizeof(*cep));
cep = dev->priv;
spin_lock_init(&cep->lock);
/* Create an Ethernet device instance.
*/
dev = init_etherdev(0, 0);
/* Get pointer to SCC area in parameter RAM.
*/
ep = (scc_enet_t *)(&immap->im_dprambase[PROFF_ENET]);
......@@ -771,6 +767,7 @@ static int __init scc_enet_init(void)
/* Allocate a page.
*/
mem_addr = __get_free_page(GFP_KERNEL);
/* BUG: no check for failure */
/* Initialize the BD for every fragment in the page.
*/
......@@ -808,6 +805,7 @@ static int __init scc_enet_init(void)
/* Install our interrupt handler.
*/
request_irq(SIU_INT_ENET, scc_enet_interrupt, 0, "enet", dev);
/* BUG: no check for failure */
/* Set GSMR_H to enable all normal operating modes.
* Set GSMR_L to enable Ethernet to MC68160.
......@@ -837,7 +835,6 @@ static int __init scc_enet_init(void)
io->iop_pdatc |= PC_EST8260_ENET_NOTFD;
dev->base_addr = (unsigned long)ep;
dev->priv = cep;
/* The CPM Ethernet specific entries in the device structure. */
dev->open = scc_enet_open;
......@@ -852,6 +849,12 @@ static int __init scc_enet_init(void)
*/
sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
err = register_netdev(dev);
if (err) {
kfree(dev);
return err;
}
printk("%s: SCC ENET Version 0.1, ", dev->name);
for (i=0; i<5; i++)
printk("%02x:", dev->dev_addr[i]);
......
......@@ -1328,7 +1328,7 @@ static int __init fec_enet_init(void)
struct net_device *dev;
struct fcc_enet_private *cep;
fcc_info_t *fip;
int i, np;
int i, np, err;
volatile immap_t *immap;
volatile iop8260_t *io;
......@@ -1339,23 +1339,16 @@ static int __init fec_enet_init(void)
fip = fcc_ports;
while (np-- > 0) {
/* Allocate some private information.
/* Create an Ethernet device instance.
*/
cep = (struct fcc_enet_private *)
kmalloc(sizeof(*cep), GFP_KERNEL);
if (cep == NULL)
dev = alloc_etherdev(sizeof(*cep));
if (!dev)
return -ENOMEM;
__clear_user(cep,sizeof(*cep));
cep = dev->priv;
spin_lock_init(&cep->lock);
cep->fip = fip;
/* Create an Ethernet device instance.
*/
dev = init_etherdev(0, 0);
dev->priv = cep;
init_fcc_shutdown(fip, cep, immap);
init_fcc_ioports(fip, io, immap);
init_fcc_param(fip, dev, immap);
......@@ -1376,6 +1369,12 @@ static int __init fec_enet_init(void)
init_fcc_startup(fip, dev);
err = register_netdev(dev);
if (err) {
kfree(dev);
return err;
}
printk("%s: FCC ENET Version 0.3, ", dev->name);
for (i=0; i<5; i++)
printk("%02x:", dev->dev_addr[i]);
......
......@@ -643,7 +643,7 @@ static int __init scc_enet_init(void)
{
struct net_device *dev;
struct scc_enet_private *cep;
int i, j, k;
int i, j, k, err;
unsigned char *eap, *ba;
dma_addr_t mem_addr;
bd_t *bd;
......@@ -659,19 +659,13 @@ static int __init scc_enet_init(void)
bd = (bd_t *)__res;
/* Allocate some private information.
*/
cep = (struct scc_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
if (cep == NULL)
dev = alloc_etherdev(sizeof(*cep));
if (!dev)
return -ENOMEM;
__clear_user(cep,sizeof(*cep));
cep = dev->priv;
spin_lock_init(&cep->lock);
/* Create an Ethernet device instance.
*/
dev = init_etherdev(0, 0);
/* Get pointer to SCC area in parameter RAM.
*/
ep = (scc_enet_t *)(&cp->cp_dparam[PROFF_ENET]);
......@@ -841,6 +835,7 @@ static int __init scc_enet_init(void)
/* Allocate a page.
*/
ba = (unsigned char *)consistent_alloc(GFP_KERNEL, PAGE_SIZE, &mem_addr);
/* BUG: no check for failure */
/* Initialize the BD for every fragment in the page.
*/
......@@ -939,7 +934,6 @@ static int __init scc_enet_init(void)
#endif
dev->base_addr = (unsigned long)ep;
dev->priv = cep;
#if 0
dev->name = "CPM_ENET";
#endif
......@@ -953,6 +947,12 @@ static int __init scc_enet_init(void)
dev->get_stats = scc_enet_get_stats;
dev->set_multicast_list = set_multicast_list;
err = register_netdev(dev);
if (err) {
kfree(dev);
return err;
}
/* And last, enable the transmit and receive processing.
*/
sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
......
......@@ -1570,7 +1570,7 @@ static int __init fec_enet_init(void)
{
struct net_device *dev;
struct fec_enet_private *fep;
int i, j, k;
int i, j, k, err;
unsigned char *eap, *iap, *ba;
unsigned long mem_addr;
volatile cbd_t *bdp;
......@@ -1586,17 +1586,11 @@ static int __init fec_enet_init(void)
bd = (bd_t *)__res;
/* Allocate some private information.
*/
fep = (struct fec_enet_private *)kmalloc(sizeof(*fep), GFP_KERNEL);
if (fep == NULL)
dev = alloc_etherdev(sizeof(*fep));
if (!dev)
return -ENOMEM;
__clear_user(fep,sizeof(*fep));
/* Create an Ethernet device instance.
*/
dev = init_etherdev(0, 0);
fep = dev->priv;
fecp = &(immap->im_cpm.cp_fec);
......@@ -1661,6 +1655,7 @@ static int __init fec_enet_init(void)
/* Allocate a page.
*/
ba = (unsigned char *)consistent_alloc(GFP_KERNEL, PAGE_SIZE, &mem_addr);
/* BUG: no check for failure */
/* Initialize the BD for every fragment in the page.
*/
......@@ -1715,7 +1710,6 @@ static int __init fec_enet_init(void)
#endif
dev->base_addr = (unsigned long)fecp;
dev->priv = fep;
/* The FEC Ethernet specific entries in the device structure. */
dev->open = fec_enet_open;
......@@ -1752,6 +1746,12 @@ static int __init fec_enet_init(void)
fecp->fec_mii_speed = 0; /* turn off MDIO */
#endif /* CONFIG_USE_MDIO */
err = register_netdev(dev);
if (err) {
kfree(dev);
return err;
}
printk ("%s: FEC ENET Version 0.2, FEC irq %d"
#ifdef PHY_INTERRUPT
", MII irq %d"
......
......@@ -184,8 +184,8 @@ extern struct dn_fib_table *dn_fib_tables[];
#else /* Endnode */
#define dn_fib_init() (0)
#define dn_fib_cleanup() (0)
#define dn_fib_init() do { } while(0)
#define dn_fib_cleanup() do { } while(0)
#define dn_fib_lookup(fl, res) (-ESRCH)
#define dn_fib_info_put(fi) do { } while(0)
......
......@@ -299,7 +299,8 @@ extern int ipv6_rcv(struct sk_buff *skb,
extern int ip6_xmit(struct sock *sk,
struct sk_buff *skb,
struct flowi *fl,
struct ipv6_txoptions *opt);
struct ipv6_txoptions *opt,
int ipfragok);
extern int ip6_nd_hdr(struct sock *sk,
struct sk_buff *skb,
......@@ -315,7 +316,7 @@ extern int ip6_build_xmit(struct sock *sk,
unsigned length,
struct ipv6_txoptions *opt,
int hlimit, int flags);
extern int ip6_found_nexthdr(struct sk_buff *skb, u8 **nexthdr);
extern int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr);
extern int ip6_append_data(struct sock *sk,
int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb),
......
......@@ -790,7 +790,8 @@ void xfrm6_policy_init(void);
struct xfrm_policy *xfrm_policy_alloc(int gfp);
extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *);
int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
struct xfrm_policy *xfrm_policy_delete(int dir, struct xfrm_selector *sel);
struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel,
int delete);
struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete);
void xfrm_policy_flush(void);
u32 xfrm_get_acqseq(void);
......
......@@ -39,57 +39,6 @@
#define MAX_SG_ONSTACK 4
/* BUGS:
* - we assume replay seqno is always present.
*/
/* Move to common area: it is shared with AH. */
/* Common with AH after some work on arguments. */
static int get_offset(u8 *packet, u32 packet_len, u8 *nexthdr, struct ipv6_opt_hdr **prevhdr)
{
u16 offset = sizeof(struct ipv6hdr);
struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(packet + offset);
u8 nextnexthdr;
*nexthdr = ((struct ipv6hdr*)packet)->nexthdr;
while (offset + 1 < packet_len) {
switch (*nexthdr) {
case NEXTHDR_HOP:
case NEXTHDR_ROUTING:
offset += ipv6_optlen(exthdr);
*nexthdr = exthdr->nexthdr;
*prevhdr = exthdr;
exthdr = (struct ipv6_opt_hdr*)(packet + offset);
break;
case NEXTHDR_DEST:
nextnexthdr =
((struct ipv6_opt_hdr*)(packet + offset + ipv6_optlen(exthdr)))->nexthdr;
/* XXX We know the option is inner dest opt
with next next header check. */
if (nextnexthdr != NEXTHDR_HOP &&
nextnexthdr != NEXTHDR_ROUTING &&
nextnexthdr != NEXTHDR_DEST) {
return offset;
}
offset += ipv6_optlen(exthdr);
*nexthdr = exthdr->nexthdr;
*prevhdr = exthdr;
exthdr = (struct ipv6_opt_hdr*)(packet + offset);
break;
default :
return offset;
}
}
return offset;
}
int esp6_output(struct sk_buff *skb)
{
int err;
......@@ -101,12 +50,12 @@ int esp6_output(struct sk_buff *skb)
struct crypto_tfm *tfm;
struct esp_data *esp;
struct sk_buff *trailer;
struct ipv6_opt_hdr *prevhdr = NULL;
int blksize;
int clen;
int alen;
int nfrags;
u8 nexthdr;
u8 *prevhdr;
u8 nexthdr = 0;
/* First, if the skb is not checksummed, complete checksum. */
if (skb->ip_summed == CHECKSUM_HW && skb_checksum_help(skb) == NULL) {
......@@ -123,7 +72,9 @@ int esp6_output(struct sk_buff *skb)
/* Strip IP header in transport mode. Save it. */
if (!x->props.mode) {
hdr_len = get_offset(skb->nh.raw, skb->len, &nexthdr, &prevhdr);
hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
nexthdr = *prevhdr;
*prevhdr = IPPROTO_ESP;
iph = kmalloc(hdr_len, GFP_ATOMIC);
if (!iph) {
err = -ENOMEM;
......@@ -178,18 +129,12 @@ int esp6_output(struct sk_buff *skb)
ipv6_addr_copy(&top_iph->daddr,
(struct in6_addr *)&x->id.daddr);
} else {
/* XXX exthdr */
esph = (struct ipv6_esp_hdr*)skb_push(skb, x->props.header_len);
skb->h.raw = (unsigned char*)esph;
top_iph = (struct ipv6hdr*)skb_push(skb, hdr_len);
memcpy(top_iph, iph, hdr_len);
kfree(iph);
top_iph->payload_len = htons(skb->len + alen - sizeof(struct ipv6hdr));
if (prevhdr) {
prevhdr->nexthdr = IPPROTO_ESP;
} else {
top_iph->nexthdr = IPPROTO_ESP;
}
*(u8*)(trailer->tail - 1) = nexthdr;
}
......@@ -302,6 +247,7 @@ int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_b
struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags];
struct scatterlist *sg = sgbuf;
u8 padlen;
u8 *prevhdr;
if (unlikely(nfrags > MAX_SG_ONSTACK)) {
sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
......@@ -325,11 +271,13 @@ int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_b
}
/* ... check padding bits here. Silly. :-) */
ret_nexthdr = ((struct ipv6hdr*)tmp_hdr)->nexthdr = nexthdr[1];
pskb_trim(skb, skb->len - alen - padlen - 2);
skb->h.raw = skb_pull(skb, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen);
skb->nh.raw += sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
memcpy(skb->nh.raw, tmp_hdr, hdr_len);
skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
ip6_find_1stfragopt(skb, &prevhdr);
ret_nexthdr = *prevhdr = nexthdr[1];
}
kfree(tmp_hdr);
return ret_nexthdr;
......
......@@ -145,7 +145,7 @@ static inline int ip6_input_finish(struct sk_buff *skb)
nexthdr = skb->nh.ipv6h->nexthdr;
nhoff = offsetof(struct ipv6hdr, nexthdr);
/* Skip hop-by-hop options, they are already parsed. */
/* Skip hop-by-hop options, they are already parsed. */
if (nexthdr == NEXTHDR_HOP) {
nhoff = sizeof(struct ipv6hdr);
nexthdr = skb->h.raw[0];
......
......@@ -196,7 +196,7 @@ static inline int ip6_maybe_reroute(struct sk_buff *skb)
*/
int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
struct ipv6_txoptions *opt)
struct ipv6_txoptions *opt, int ipfragok)
{
struct ipv6_pinfo *np = sk ? inet6_sk(sk) : NULL;
struct in6_addr *first_hop = &fl->fl6_dst;
......@@ -258,13 +258,14 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
ipv6_addr_copy(&hdr->daddr, first_hop);
mtu = dst_pmtu(dst);
if (skb->len <= mtu) {
if ((skb->len <= mtu) || ipfragok) {
IP6_INC_STATS(Ip6OutRequests);
return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute);
}
if (net_ratelimit())
printk(KERN_DEBUG "IPv6: sending pkt_too_big to self\n");
skb->dev = dst->dev;
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
kfree_skb(skb);
return -EMSGSIZE;
......@@ -381,7 +382,7 @@ static int ip6_frag_xmit(struct sock *sk, inet_getfrag_t getfrag,
/*
* Length of fragmented part on every packet but
* the last must be an:
* "integer multiple of 8 octects".
* "integer multiple of 8 octets".
*/
frag_len = (mtu - unfrag_len) & ~0x7;
......@@ -587,7 +588,7 @@ int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
if (err) {
#if IP6_DEBUG >= 2
printk(KERN_DEBUG "ip6_build_xmit: "
"no availiable source address\n");
"no available source address\n");
#endif
goto out;
}
......@@ -887,7 +888,7 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
#endif
}
int ip6_found_nexthdr(struct sk_buff *skb, u8 **nexthdr)
int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
{
u16 offset = sizeof(struct ipv6hdr);
struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.ipv6h + 1);
......@@ -929,7 +930,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
u8 *prevhdr, nexthdr = 0;
dev = rt->u.dst.dev;
hlen = ip6_found_nexthdr(skb, &prevhdr);
hlen = ip6_find_1stfragopt(skb, &prevhdr);
nexthdr = *prevhdr;
mtu = dst_pmtu(&rt->u.dst) - hlen - sizeof(struct frag_hdr);
......@@ -1187,7 +1188,7 @@ int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
if (err) {
#if IP6_DEBUG >= 2
printk(KERN_DEBUG "ip6_build_xmit: "
"no availiable source address\n");
"no available source address\n");
#endif
return err;
}
......
......@@ -105,7 +105,7 @@ static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, s
iph = skb->nh.ipv6h;
iph->payload_len = htons(skb->len);
ip6_found_nexthdr(skb, &prevhdr);
ip6_find_1stfragopt(skb, &prevhdr);
*prevhdr = nexthdr;
out:
if (tmp_hdr)
......@@ -160,7 +160,7 @@ static int ipcomp6_output(struct sk_buff *skb)
skb->nh.raw = skb->data; /* == top_iph */
skb->h.raw = skb->nh.raw + hdr_len;
} else {
hdr_len = ip6_found_nexthdr(skb, &prevhdr);
hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
nexthdr = *prevhdr;
}
......@@ -203,7 +203,7 @@ static int ipcomp6_output(struct sk_buff *skb)
top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
skb->nh.raw = skb->data; /* top_iph */
ip6_found_nexthdr(skb, &prevhdr);
ip6_find_1stfragopt(skb, &prevhdr);
*prevhdr = IPPROTO_COMP;
ipch = (struct ipv6_comp_hdr *)((unsigned char *)top_iph + hdr_len);
......
......@@ -35,6 +35,6 @@ EXPORT_SYMBOL(ipv6_chk_addr);
EXPORT_SYMBOL(in6addr_any);
EXPORT_SYMBOL(in6addr_loopback);
EXPORT_SYMBOL(in6_dev_finish_destroy);
EXPORT_SYMBOL(ip6_found_nexthdr);
EXPORT_SYMBOL(ip6_find_1stfragopt);
EXPORT_SYMBOL(xfrm6_rcv);
EXPORT_SYMBOL(xfrm6_clear_mutable_options);
......@@ -939,7 +939,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req,
csum_partial((char *)th, skb->len, skb->csum));
ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr);
err = ip6_xmit(sk, skb, &fl, opt);
err = ip6_xmit(sk, skb, &fl, opt, 0);
if (err == NET_XMIT_CN)
err = 0;
}
......@@ -1057,7 +1057,7 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
buff->dst = ip6_route_output(NULL, &fl);
if (buff->dst->error == 0) {
ip6_xmit(NULL, buff, &fl, NULL);
ip6_xmit(NULL, buff, &fl, NULL, 0);
TCP_INC_STATS_BH(TcpOutSegs);
TCP_INC_STATS_BH(TcpOutRsts);
return;
......@@ -1120,7 +1120,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
buff->dst = ip6_route_output(NULL, &fl);
if (buff->dst->error == 0) {
ip6_xmit(NULL, buff, &fl, NULL);
ip6_xmit(NULL, buff, &fl, NULL, 0);
TCP_INC_STATS_BH(TcpOutSegs);
return;
}
......@@ -1823,7 +1823,7 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok)
/* Restore final destination back after routing done */
ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
return ip6_xmit(sk, skb, &fl, np->opt);
return ip6_xmit(sk, skb, &fl, np->opt, 0);
}
static void v6_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr)
......
......@@ -1990,7 +1990,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
if (sel.dport)
sel.dport_mask = ~0;
xp = xfrm_policy_delete(pol->sadb_x_policy_dir-1, &sel);
xp = xfrm_policy_bysel(pol->sadb_x_policy_dir-1, &sel, 1);
if (xp == NULL)
return -ENOENT;
......
......@@ -337,7 +337,7 @@ EXPORT_SYMBOL(xfrm_find_acq);
EXPORT_SYMBOL(xfrm_alloc_spi);
EXPORT_SYMBOL(xfrm_state_flush);
EXPORT_SYMBOL(xfrm_policy_kill);
EXPORT_SYMBOL(xfrm_policy_delete);
EXPORT_SYMBOL(xfrm_policy_bysel);
EXPORT_SYMBOL(xfrm_policy_insert);
EXPORT_SYMBOL(xfrm_policy_walk);
EXPORT_SYMBOL(xfrm_policy_flush);
......
......@@ -176,7 +176,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport,
SCTP_INC_STATS(SctpOutSCTPPacks);
return ip6_xmit(sk, skb, &fl, np->opt);
return ip6_xmit(sk, skb, &fl, np->opt, ipfragok);
}
/* Returns the dst cache entry for the given source and destination ip
......
......@@ -878,8 +878,6 @@ int sctp_register_pf(struct sctp_pf *pf, sa_family_t family)
static int __init init_sctp_mibs(void)
{
int i;
sctp_statistics[0] = alloc_percpu(struct sctp_mib);
if (!sctp_statistics[0])
return -ENOMEM;
......
......@@ -297,19 +297,25 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
return 0;
}
struct xfrm_policy *xfrm_policy_delete(int dir, struct xfrm_selector *sel)
struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel,
int delete)
{
struct xfrm_policy *pol, **p;
write_lock_bh(&xfrm_policy_lock);
for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) {
if (memcmp(sel, &pol->selector, sizeof(*sel)) == 0) {
*p = pol->next;
if (delete)
*p = pol->next;
break;
}
}
if (pol)
atomic_inc(&flow_cache_genid);
if (pol) {
if (delete)
atomic_inc(&flow_cache_genid);
else
xfrm_pol_hold(pol);
}
write_unlock_bh(&xfrm_policy_lock);
return pol;
}
......
......@@ -656,26 +656,6 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
return 0;
}
static int xfrm_del_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
{
struct xfrm_policy *xp;
struct xfrm_userpolicy_id *p;
int err;
p = NLMSG_DATA(nlh);
err = verify_policy_dir(p->dir);
if (err)
return err;
xp = xfrm_policy_delete(p->dir, &p->sel);
if (xp == NULL)
return -ENOENT;
xfrm_policy_kill(xp);
xfrm_pol_put(xp);
return 0;
}
static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr)
{
struct xfrm_dump_info *sp = ptr;
......@@ -774,20 +754,36 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
{
struct xfrm_policy *xp;
struct xfrm_userpolicy_id *p;
struct sk_buff *resp_skb;
int err;
int delete;
p = NLMSG_DATA(nlh);
xp = xfrm_policy_byid(p->dir, p->index, 0);
delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY;
err = verify_policy_dir(p->dir);
if (err)
return err;
if (p->index)
xp = xfrm_policy_byid(p->dir, p->index, delete);
else
xp = xfrm_policy_bysel(p->dir, &p->sel, delete);
if (xp == NULL)
return -ENOENT;
resp_skb = xfrm_policy_netlink(skb, xp, p->dir, nlh->nlmsg_seq);
if (IS_ERR(resp_skb)) {
err = PTR_ERR(resp_skb);
} else {
err = netlink_unicast(xfrm_nl, resp_skb,
NETLINK_CB(skb).pid, MSG_DONTWAIT);
if (delete)
xfrm_policy_kill(xp);
else {
struct sk_buff *resp_skb;
resp_skb = xfrm_policy_netlink(skb, xp, p->dir, nlh->nlmsg_seq);
if (IS_ERR(resp_skb)) {
err = PTR_ERR(resp_skb);
} else {
err = netlink_unicast(xfrm_nl, resp_skb,
NETLINK_CB(skb).pid,
MSG_DONTWAIT);
}
}
xfrm_pol_put(xp);
......@@ -819,7 +815,7 @@ static struct xfrm_link {
.dump = xfrm_dump_sa,
},
{ .doit = xfrm_add_policy },
{ .doit = xfrm_del_policy },
{ .doit = xfrm_get_policy },
{
.doit = xfrm_get_policy,
.dump = xfrm_dump_policy,
......
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