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; }
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; }
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; }
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; }
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); }
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); }