OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [atm/] [addr.c] - Diff between revs 1275 and 1765

Only display areas with differences | Details | Blame | View Log

Rev 1275 Rev 1765
/* net/atm/addr.c - Local ATM address registry */
/* net/atm/addr.c - Local ATM address registry */
 
 
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
 
 
 
 
#include <linux/atm.h>
#include <linux/atm.h>
#include <linux/atmdev.h>
#include <linux/atmdev.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
 
 
#include "signaling.h"
#include "signaling.h"
#include "addr.h"
#include "addr.h"
 
 
 
 
static int check_addr(struct sockaddr_atmsvc *addr)
static int check_addr(struct sockaddr_atmsvc *addr)
{
{
        int i;
        int i;
 
 
        if (addr->sas_family != AF_ATMSVC) return -EAFNOSUPPORT;
        if (addr->sas_family != AF_ATMSVC) return -EAFNOSUPPORT;
        if (!*addr->sas_addr.pub)
        if (!*addr->sas_addr.pub)
                return *addr->sas_addr.prv ? 0 : -EINVAL;
                return *addr->sas_addr.prv ? 0 : -EINVAL;
        for (i = 1; i < ATM_E164_LEN+1; i++) /* make sure it's \0-terminated */
        for (i = 1; i < ATM_E164_LEN+1; i++) /* make sure it's \0-terminated */
                if (!addr->sas_addr.pub[i]) return 0;
                if (!addr->sas_addr.pub[i]) return 0;
        return -EINVAL;
        return -EINVAL;
}
}
 
 
 
 
static int identical(struct sockaddr_atmsvc *a,struct sockaddr_atmsvc *b)
static int identical(struct sockaddr_atmsvc *a,struct sockaddr_atmsvc *b)
{
{
        if (*a->sas_addr.prv)
        if (*a->sas_addr.prv)
                if (memcmp(a->sas_addr.prv,b->sas_addr.prv,ATM_ESA_LEN))
                if (memcmp(a->sas_addr.prv,b->sas_addr.prv,ATM_ESA_LEN))
                        return 0;
                        return 0;
        if (!*a->sas_addr.pub) return !*b->sas_addr.pub;
        if (!*a->sas_addr.pub) return !*b->sas_addr.pub;
        if (!*b->sas_addr.pub) return 0;
        if (!*b->sas_addr.pub) return 0;
        return !strcmp(a->sas_addr.pub,b->sas_addr.pub);
        return !strcmp(a->sas_addr.pub,b->sas_addr.pub);
}
}
 
 
 
 
static void notify_sigd(struct atm_dev *dev)
static void notify_sigd(struct atm_dev *dev)
{
{
        struct sockaddr_atmpvc pvc;
        struct sockaddr_atmpvc pvc;
 
 
        pvc.sap_addr.itf = dev->number;
        pvc.sap_addr.itf = dev->number;
        sigd_enq(NULL,as_itf_notify,NULL,&pvc,NULL);
        sigd_enq(NULL,as_itf_notify,NULL,&pvc,NULL);
}
}
 
 
 
 
void atm_reset_addr(struct atm_dev *dev)
void atm_reset_addr(struct atm_dev *dev)
{
{
        unsigned long flags;
        unsigned long flags;
        struct atm_dev_addr *this;
        struct atm_dev_addr *this;
 
 
        spin_lock_irqsave(&dev->lock, flags);
        spin_lock_irqsave(&dev->lock, flags);
        while (dev->local) {
        while (dev->local) {
                this = dev->local;
                this = dev->local;
                dev->local = this->next;
                dev->local = this->next;
                kfree(this);
                kfree(this);
        }
        }
        spin_unlock_irqrestore(&dev->lock, flags);
        spin_unlock_irqrestore(&dev->lock, flags);
        notify_sigd(dev);
        notify_sigd(dev);
}
}
 
 
 
 
int atm_add_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr)
int atm_add_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr)
{
{
        unsigned long flags;
        unsigned long flags;
        struct atm_dev_addr **walk;
        struct atm_dev_addr **walk;
        int error;
        int error;
 
 
        error = check_addr(addr);
        error = check_addr(addr);
        if (error)
        if (error)
                return error;
                return error;
        spin_lock_irqsave(&dev->lock, flags);
        spin_lock_irqsave(&dev->lock, flags);
        for (walk = &dev->local; *walk; walk = &(*walk)->next)
        for (walk = &dev->local; *walk; walk = &(*walk)->next)
                if (identical(&(*walk)->addr,addr)) {
                if (identical(&(*walk)->addr,addr)) {
                        spin_unlock_irqrestore(&dev->lock, flags);
                        spin_unlock_irqrestore(&dev->lock, flags);
                        return -EEXIST;
                        return -EEXIST;
                }
                }
        *walk = kmalloc(sizeof(struct atm_dev_addr), GFP_ATOMIC);
        *walk = kmalloc(sizeof(struct atm_dev_addr), GFP_ATOMIC);
        if (!*walk) {
        if (!*walk) {
                spin_unlock_irqrestore(&dev->lock, flags);
                spin_unlock_irqrestore(&dev->lock, flags);
                return -ENOMEM;
                return -ENOMEM;
        }
        }
        (*walk)->addr = *addr;
        (*walk)->addr = *addr;
        (*walk)->next = NULL;
        (*walk)->next = NULL;
        spin_unlock_irqrestore(&dev->lock, flags);
        spin_unlock_irqrestore(&dev->lock, flags);
        notify_sigd(dev);
        notify_sigd(dev);
        return 0;
        return 0;
}
}
 
 
 
 
int atm_del_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr)
int atm_del_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr)
{
{
        unsigned long flags;
        unsigned long flags;
        struct atm_dev_addr **walk,*this;
        struct atm_dev_addr **walk,*this;
        int error;
        int error;
 
 
        error = check_addr(addr);
        error = check_addr(addr);
        if (error)
        if (error)
                return error;
                return error;
        spin_lock_irqsave(&dev->lock, flags);
        spin_lock_irqsave(&dev->lock, flags);
        for (walk = &dev->local; *walk; walk = &(*walk)->next)
        for (walk = &dev->local; *walk; walk = &(*walk)->next)
                if (identical(&(*walk)->addr,addr)) break;
                if (identical(&(*walk)->addr,addr)) break;
        if (!*walk) {
        if (!*walk) {
                spin_unlock_irqrestore(&dev->lock, flags);
                spin_unlock_irqrestore(&dev->lock, flags);
                return -ENOENT;
                return -ENOENT;
        }
        }
        this = *walk;
        this = *walk;
        *walk = this->next;
        *walk = this->next;
        kfree(this);
        kfree(this);
        spin_unlock_irqrestore(&dev->lock, flags);
        spin_unlock_irqrestore(&dev->lock, flags);
        notify_sigd(dev);
        notify_sigd(dev);
        return 0;
        return 0;
}
}
 
 
 
 
int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc *u_buf,int size)
int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc *u_buf,int size)
{
{
        unsigned long flags;
        unsigned long flags;
        struct atm_dev_addr *walk;
        struct atm_dev_addr *walk;
        int total = 0, error;
        int total = 0, error;
        struct sockaddr_atmsvc *tmp_buf, *tmp_bufp;
        struct sockaddr_atmsvc *tmp_buf, *tmp_bufp;
 
 
 
 
        spin_lock_irqsave(&dev->lock, flags);
        spin_lock_irqsave(&dev->lock, flags);
        for (walk = dev->local; walk; walk = walk->next)
        for (walk = dev->local; walk; walk = walk->next)
                total += sizeof(struct sockaddr_atmsvc);
                total += sizeof(struct sockaddr_atmsvc);
        tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC);
        tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC);
        if (!tmp_buf) {
        if (!tmp_buf) {
                spin_unlock_irqrestore(&dev->lock, flags);
                spin_unlock_irqrestore(&dev->lock, flags);
                return -ENOMEM;
                return -ENOMEM;
        }
        }
        for (walk = dev->local; walk; walk = walk->next)
        for (walk = dev->local; walk; walk = walk->next)
                memcpy(tmp_bufp++, &walk->addr, sizeof(struct sockaddr_atmsvc));
                memcpy(tmp_bufp++, &walk->addr, sizeof(struct sockaddr_atmsvc));
        spin_unlock_irqrestore(&dev->lock, flags);
        spin_unlock_irqrestore(&dev->lock, flags);
        error = total > size ? -E2BIG : total;
        error = total > size ? -E2BIG : total;
        if (copy_to_user(u_buf, tmp_buf, total < size ? total : size))
        if (copy_to_user(u_buf, tmp_buf, total < size ? total : size))
                error = -EFAULT;
                error = -EFAULT;
        kfree(tmp_buf);
        kfree(tmp_buf);
        return error;
        return error;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.