Esempio n. 1
0
static int clip_arp_rcv(struct sk_buff *skb)
{
	struct atm_vcc *vcc;

	DPRINTK("clip_arp_rcv\n");
	vcc = ATM_SKB(skb)->vcc;
	if (!vcc || !atm_charge(vcc,skb->truesize)) {
		dev_kfree_skb_any(skb);
		return 0;
	}
	DPRINTK("pushing to %p\n",vcc);
	DPRINTK("using %p\n",CLIP_VCC(vcc)->old_push);
	CLIP_VCC(vcc)->old_push(vcc,skb);
	return 0;
}
Esempio 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;
}
Esempio n. 3
0
static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc)
{
	static const char *const class_name[] = {
		"off", "UBR", "CBR", "VBR", "ABR"};
	static const char *const aal_name[] = {
		"---",	"1",	"2",	"3/4",	/*  0- 3 */
		"???",	"5",	"???",	"???",	/*  4- 7 */
		"???",	"???",	"???",	"???",	/*  8-11 */
		"???",	"0",	"???",	"???"};	/* 12-15 */

	seq_printf(seq, "%3d %3d %5d %-3s %7d %-5s %7d %-6s",
		   vcc->dev->number, vcc->vpi, vcc->vci,
		   vcc->qos.aal >= ARRAY_SIZE(aal_name) ? "err" :
		   aal_name[vcc->qos.aal], vcc->qos.rxtp.min_pcr,
		   class_name[vcc->qos.rxtp.traffic_class],
		   vcc->qos.txtp.min_pcr,
		   class_name[vcc->qos.txtp.traffic_class]);
	if (test_bit(ATM_VF_IS_CLIP, &vcc->flags)) {
		struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
		struct net_device *dev;

		dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : NULL;
		seq_printf(seq, "CLIP, Itf:%s, Encap:",
		    dev ? dev->name : "none?");
		seq_printf(seq, "%s", clip_vcc->encap ? "LLC/SNAP" : "None");
	}
	seq_putc(seq, '\n');
}
Esempio n. 4
0
static int clip_inarp_send(struct atm_vcc *vcc, u32 remote_ip, u16 op)
{
    struct sk_buff *skb;
    int allocated_size, error, size = 0;
    u8 *buff;
    u32 local_ip;
    struct atmarphdr *hdr;

    if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
	test_bit(ATM_VF_CLOSE, &vcc->flags))
    {
	return vcc->reply;
    }
    if (!test_bit(ATM_VF_READY, &vcc->flags))
	return -EPIPE;
    
    /* align to word boundary */
    allocated_size = (MAX_ATMARP_SIZE + RFC1483LLC_LEN + 3) & ~3;

    if (atomic_read(&vcc->tx_inuse) && !atm_may_send(vcc, allocated_size))
    {
	DPRINTK("Sorry: tx_inuse = %d, size = %d, sndbuf = %d\n",
	    atomic_read(&vcc->tx_inuse), allocated_size, vcc->sk->sndbuf);
	return -1;
    }
    if(!(skb = alloc_skb(allocated_size, GFP_ATOMIC)))
	return -1;
    DPRINTK("AlTx %d += %d\n",atomic_read(&vcc->tx_inuse), skb->truesize);
    atomic_add(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);

    skb->dev = NULL; /* for paths shared with net_device interfaces */
    ATM_SKB(skb)->iovcnt = 0;
    ATM_SKB(skb)->atm_options = vcc->atm_options;
    buff = skb->data;
    memcpy(buff, llc_oui_arp, RFC1483LLC_LEN);
    hdr = (struct atmarphdr *) (buff + RFC1483LLC_LEN);
    memset(hdr, 0, MAX_ATMARP_SIZE);
    hdr->ar_hrd = htons(ARPHRD_ATM);
    hdr->ar_pro = htons(ETH_P_IP);
    hdr->ar_op = htons(op);
    local_ip = clip_vcc_to_local_ip(CLIP_VCC(vcc));
    size = hdr->data - buff;
    /* XXX: htonl might be needed */
    memcpy(hdr->data, &local_ip, sizeof(u32));
    hdr->ar_spln = sizeof(u32);
    size += sizeof(u32);
    if (remote_ip)
    {
	/* XXX: htonl might be needed */
	memcpy(hdr->data + sizeof(u32), &remote_ip, sizeof(u32));
	hdr->ar_tpln = sizeof(u32);
	size += sizeof(u32);
    }

    skb_put(skb, size);
    if (allocated_size != size)
	memset(skb->data + size, 0, allocated_size - size);
    error = vcc->dev->ops->send(vcc,skb);
    return error ? error : size;
}
Esempio n. 5
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;
}
Esempio 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);
}
Esempio n. 7
0
static int clip_arp_rcv(struct sk_buff *skb)
{
    struct atm_vcc *vcc;

    DPRINTK("clip_arp_rcv\n");
    vcc = ATM_SKB(skb)->vcc;
    if (!vcc)
	goto Exit;

    incoming_arp(CLIP_VCC(vcc), (struct atmarphdr *)skb->data, skb->len);

Exit:
    dev_kfree_skb_any(skb);
    return 0;
}
Esempio n. 8
0
static void clip_pop(struct atm_vcc *vcc,struct sk_buff *skb)
{
	struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
	struct net_device *dev = skb->dev;
	int old;
	unsigned long flags;

	DPRINTK("clip_pop(vcc %p)\n",vcc);
	clip_vcc->old_pop(vcc,skb);
	/* skb->dev == NULL in outbound ARP packets */
	if (!dev) return;
	spin_lock_irqsave(&PRIV(dev)->xoff_lock,flags);
	if (atm_may_send(vcc,0)) {
		old = xchg(&clip_vcc->xoff,0);
		if (old) netif_wake_queue(dev);
	}
	spin_unlock_irqrestore(&PRIV(dev)->xoff_lock,flags);
}
Esempio n. 9
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;
}
Esempio n. 11
0
void clip_push(struct atm_vcc *vcc,struct sk_buff *skb)
{
    struct clip_vcc *clip_vcc = CLIP_VCC(vcc);

    DPRINTK("clip push\n");
    if (!skb)
    {
	clip_vcc_remove(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->mac.raw = skb->data;
    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 = ((u16 *) skb->data)[3];
	skb_pull(skb, RFC1483LLC_LEN);
	if (skb->protocol == htons(ETH_P_ARP))
	{
	    PRIV(skb->dev)->stats.rx_packets++;
	    PRIV(skb->dev)->stats.rx_bytes += skb->len;
	    clip_arp_rcv(skb);
	    return;
	}
    }
    clip_vcc->last_use = jiffies;
    PRIV(skb->dev)->stats.rx_packets++;
    PRIV(skb->dev)->stats.rx_bytes += skb->len;
    netif_rx(skb);
}
Esempio n. 12
0
static int clip_encap(struct atm_vcc *vcc,int mode)
{
	CLIP_VCC(vcc)->encap = mode;
	return 0;
}