Ejemplo n.º 1
0
static int clip_setentry(struct atm_vcc *vcc,u32 ip)
{
	struct neighbour *neigh;
	struct atmarp_entry *entry;
	int error;
	struct clip_vcc *clip_vcc;
#ifndef __TCS__
	struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1 } } };
	struct rtable *rt;
#else
	struct rtable *rt;
	struct flowi fl;
	memset(&fl,0,sizeof(fl));
	fl.nl_u.ip4_u.daddr=ip;
	fl.nl_u.ip4_u.tos=1;
#endif 

	if (vcc->push != clip_push) {
		printk(KERN_WARNING "clip_setentry: non-CLIP VCC\n");
		return -EBADF;
	}
	clip_vcc = CLIP_VCC(vcc);
	if (!ip) {
		if (!clip_vcc->entry) {
			printk(KERN_ERR "hiding hidden ATMARP entry\n");
			return 0;
		}
		DPRINTK("setentry: remove\n");
		unlink_clip_vcc(clip_vcc);
		return 0;
	}
	error = ip_route_output_key(&rt,&fl);
	if (error) return error;
	neigh = __neigh_lookup(&clip_tbl,&ip,rt->u.dst.dev,1);
	ip_rt_put(rt);
	if (!neigh)
		return -ENOMEM;
	entry = NEIGH2ENTRY(neigh);
	if (entry != clip_vcc->entry) {
		if (!clip_vcc->entry) DPRINTK("setentry: add\n");
		else {
			DPRINTK("setentry: update\n");
			unlink_clip_vcc(clip_vcc);
		}
		link_vcc(clip_vcc,entry);
	}
	error = neigh_update(neigh, llc_oui, NUD_PERMANENT, 
			     NEIGH_UPDATE_F_OVERRIDE|NEIGH_UPDATE_F_ADMIN);
	neigh_release(neigh);
	return error;
}
Ejemplo n.º 2
0
static int clip_assign_device(struct atm_vcc *vcc, int itf)
{
    struct clip_vcc *clip_vcc;
    knet_netdev_t *dev;

    if (vcc->push != clip_push)
    {
	printk(KERN_WARNING "clip_assign_device: non-CLIP VCC\n");
	return -EBADF;
    }

    clip_vcc = CLIP_VCC(vcc);
    for (dev = clip_devs; dev && PRIV(dev)->number != itf;
	dev = PRIV(dev)->next);

    if (!dev)
    {
	printk(KERN_WARNING "clip_assign_device: no such device\n");
	return -ENODEV;
    }

    if (clip_vcc->entry)
	unlink_clip_vcc(clip_vcc);

    clip_vcc->dev = dev;

    clip_vcc->global_next = clip_vccs;
    clip_vccs = clip_vcc;

    clip_start_resolving(clip_vcc);

    return 0;
}
Ejemplo n.º 3
0
static int clip_setentry(struct atm_vcc *vcc, __be32 ip)
{
	struct neighbour *neigh;
	struct atmarp_entry *entry;
	int error;
	struct clip_vcc *clip_vcc;
	struct rtable *rt;

	if (vcc->push != clip_push) {
		pr_warning("non-CLIP VCC\n");
		return -EBADF;
	}
	clip_vcc = CLIP_VCC(vcc);
	if (!ip) {
		if (!clip_vcc->entry) {
			pr_err("hiding hidden ATMARP entry\n");
			return 0;
		}
		pr_debug("remove\n");
		unlink_clip_vcc(clip_vcc);
		return 0;
	}
	rt = ip_route_output(&init_net, ip, 0, 1, 0);
	if (IS_ERR(rt))
		return PTR_ERR(rt);
	neigh = __neigh_lookup(&arp_tbl, &ip, rt->dst.dev, 1);
	ip_rt_put(rt);
	if (!neigh)
		return -ENOMEM;
	entry = neighbour_priv(neigh);
	if (entry != clip_vcc->entry) {
		if (!clip_vcc->entry)
			pr_debug("add\n");
		else {
			pr_debug("update\n");
			unlink_clip_vcc(clip_vcc);
		}
		link_vcc(clip_vcc, entry);
	}
	error = neigh_update(neigh, llc_oui, NUD_PERMANENT,
			     NEIGH_UPDATE_F_OVERRIDE | NEIGH_UPDATE_F_ADMIN);
	neigh_release(neigh);
	return error;
}
int clip_setentry(struct atm_vcc *vcc,u32 ip)
{
	struct neighbour *neigh;
	struct atmarp_entry *entry;
	int error;
	struct clip_vcc *clip_vcc;
	struct rtable *rt;

	if (vcc->push != clip_push) {
		printk(KERN_WARNING "clip_setentry: non-CLIP VCC\n");
		return -EBADF;
	}
	clip_vcc = CLIP_VCC(vcc);
	if (!ip) {
		if (!clip_vcc->entry) {
			printk(KERN_ERR "hiding hidden ATMARP entry\n");
			return 0;
		}
		DPRINTK("setentry: remove\n");
		unlink_clip_vcc(clip_vcc);
		return 0;
	}
	error = ip_route_output(&rt,ip,0,1,0);
	if (error) return error;
	neigh = __neigh_lookup(&clip_tbl,&ip,rt->u.dst.dev,1);
	ip_rt_put(rt);
	if (!neigh)
		return -ENOMEM;
	entry = NEIGH2ENTRY(neigh);
	if (entry != clip_vcc->entry) {
		if (!clip_vcc->entry) DPRINTK("setentry: add\n");
		else {
			DPRINTK("setentry: update\n");
			unlink_clip_vcc(clip_vcc);
		}
		link_vcc(clip_vcc,entry);
	}
	error = neigh_update(neigh,llc_oui,NUD_PERMANENT,1,0);
	neigh_release(neigh);
	return error;
}
Ejemplo n.º 5
0
static int clip_learn(struct clip_vcc *clip_vcc, u32 ip)
{
    struct neighbour *neigh;
    struct atmarp_entry *entry;
    int error;

    if (!ip)
    {
	if (!clip_vcc->entry)
	{
	    printk(KERN_ERR "hiding hidden ATMARP entry\n");
	    return 0;
	}
	DPRINTK("setentry: remove\n");
	unlink_clip_vcc(clip_vcc);
	return 0;
    }

    neigh = __neigh_lookup(&clip_tbl, &ip, clip_vcc->dev, 1);
    if (!neigh)
	return -ENOMEM;
    del_timer(&clip_vcc->resolve_timer);
    clip_vcc->resolve_timeout = 0; /* Mark resolved */
    entry = NEIGH2ENTRY(neigh);
    if (entry != clip_vcc->entry)
    {
	if (!clip_vcc->entry)
	    DPRINTK("setentry: add\n");
	else
	{
	    DPRINTK("setentry: update %p\n", clip_vcc->entry);
	    unlink_clip_vcc(clip_vcc);
	}
	link_vcc(clip_vcc, entry);
    }
    error = neigh_update(neigh, llc_oui, NUD_PERMANENT, 1, 0);
    entry->expires = jiffies + CLIP_ENTRY_EXPIRE;
    neigh_release(neigh);
    return error;
}
Ejemplo n.º 6
0
static void clip_push(struct atm_vcc *vcc, struct sk_buff *skb)
{
	struct clip_vcc *clip_vcc = CLIP_VCC(vcc);

	pr_debug("\n");

	if (!clip_devs) {
		atm_return(vcc, skb->truesize);
		kfree_skb(skb);
		return;
	}

	if (!skb) {
		pr_debug("removing VCC %p\n", clip_vcc);
		if (clip_vcc->entry)
			unlink_clip_vcc(clip_vcc);
		clip_vcc->old_push(vcc, NULL);	/* pass on the bad news */
		kfree(clip_vcc);
		return;
	}
	atm_return(vcc, skb->truesize);
	skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs;
	/* clip_vcc->entry == NULL if we don't have an IP address yet */
	if (!skb->dev) {
		dev_kfree_skb_any(skb);
		return;
	}
	ATM_SKB(skb)->vcc = vcc;
	skb_reset_mac_header(skb);
	if (!clip_vcc->encap ||
	    skb->len < RFC1483LLC_LEN ||
	    memcmp(skb->data, llc_oui, sizeof(llc_oui)))
		skb->protocol = htons(ETH_P_IP);
	else {
		skb->protocol = ((__be16 *)skb->data)[3];
		skb_pull(skb, RFC1483LLC_LEN);
		if (skb->protocol == htons(ETH_P_ARP)) {
			skb->dev->stats.rx_packets++;
			skb->dev->stats.rx_bytes += skb->len;
			clip_arp_rcv(skb);
			return;
		}
	}
	clip_vcc->last_use = jiffies;
	skb->dev->stats.rx_packets++;
	skb->dev->stats.rx_bytes += skb->len;
	memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
	netif_rx(skb);
}
Ejemplo n.º 7
0
static void clip_vcc_remove(struct clip_vcc *clip_vcc)
{
    struct clip_vcc **find_vcc = &clip_vccs;

    DPRINTK("removing VCC %p\n", clip_vcc);
    del_timer(&clip_vcc->resolve_timer);
    if (clip_vcc->entry)
	unlink_clip_vcc(clip_vcc);
    for (find_vcc = &clip_vccs; *find_vcc && *find_vcc != clip_vcc; 
	find_vcc = &(*find_vcc)->global_next);
    if (*find_vcc)
	(*find_vcc) = (*find_vcc)->global_next;
    clip_vcc->old_push(clip_vcc->vcc, NULL); /* pass on the bad news */
    kfree(clip_vcc);
}