⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 addr.c

📁 linux 内核源代码
💻 C
字号:
/* net/atm/addr.c - Local ATM address registry *//* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */#include <linux/atm.h>#include <linux/atmdev.h>#include <asm/uaccess.h>#include "signaling.h"#include "addr.h"static int check_addr(struct sockaddr_atmsvc *addr){	int i;	if (addr->sas_family != AF_ATMSVC)		return -EAFNOSUPPORT;	if (!*addr->sas_addr.pub)		return *addr->sas_addr.prv ? 0 : -EINVAL;	for (i = 1; i < ATM_E164_LEN + 1; i++)	/* make sure it's \0-terminated */		if (!addr->sas_addr.pub[i])			return 0;	return -EINVAL;}static int identical(struct sockaddr_atmsvc *a, struct sockaddr_atmsvc *b){	if (*a->sas_addr.prv)		if (memcmp(a->sas_addr.prv, b->sas_addr.prv, ATM_ESA_LEN))			return 0;	if (!*a->sas_addr.pub)		return !*b->sas_addr.pub;	if (!*b->sas_addr.pub)		return 0;	return !strcmp(a->sas_addr.pub, b->sas_addr.pub);}static void notify_sigd(struct atm_dev *dev){	struct sockaddr_atmpvc pvc;	pvc.sap_addr.itf = dev->number;	sigd_enq(NULL, as_itf_notify, NULL, &pvc, NULL);}void atm_reset_addr(struct atm_dev *dev, enum atm_addr_type_t atype){	unsigned long flags;	struct atm_dev_addr *this, *p;	struct list_head *head;	spin_lock_irqsave(&dev->lock, flags);	if (atype == ATM_ADDR_LECS)		head = &dev->lecs;	else		head = &dev->local;	list_for_each_entry_safe(this, p, head, entry) {		list_del(&this->entry);		kfree(this);	}	spin_unlock_irqrestore(&dev->lock, flags);	if (head == &dev->local)		notify_sigd(dev);}int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr,		 enum atm_addr_type_t atype){	unsigned long flags;	struct atm_dev_addr *this;	struct list_head *head;	int error;	error = check_addr(addr);	if (error)		return error;	spin_lock_irqsave(&dev->lock, flags);	if (atype == ATM_ADDR_LECS)		head = &dev->lecs;	else		head = &dev->local;	list_for_each_entry(this, head, entry) {		if (identical(&this->addr, addr)) {			spin_unlock_irqrestore(&dev->lock, flags);			return -EEXIST;		}	}	this = kmalloc(sizeof(struct atm_dev_addr), GFP_ATOMIC);	if (!this) {		spin_unlock_irqrestore(&dev->lock, flags);		return -ENOMEM;	}	this->addr = *addr;	list_add(&this->entry, head);	spin_unlock_irqrestore(&dev->lock, flags);	if (head == &dev->local)		notify_sigd(dev);	return 0;}int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr,		 enum atm_addr_type_t atype){	unsigned long flags;	struct atm_dev_addr *this;	struct list_head *head;	int error;	error = check_addr(addr);	if (error)		return error;	spin_lock_irqsave(&dev->lock, flags);	if (atype == ATM_ADDR_LECS)		head = &dev->lecs;	else		head = &dev->local;	list_for_each_entry(this, head, entry) {		if (identical(&this->addr, addr)) {			list_del(&this->entry);			spin_unlock_irqrestore(&dev->lock, flags);			kfree(this);			if (head == &dev->local)				notify_sigd(dev);			return 0;		}	}	spin_unlock_irqrestore(&dev->lock, flags);	return -ENOENT;}int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user * buf,		 size_t size, enum atm_addr_type_t atype){	unsigned long flags;	struct atm_dev_addr *this;	struct list_head *head;	int total = 0, error;	struct sockaddr_atmsvc *tmp_buf, *tmp_bufp;	spin_lock_irqsave(&dev->lock, flags);	if (atype == ATM_ADDR_LECS)		head = &dev->lecs;	else		head = &dev->local;	list_for_each_entry(this, head, entry)	    total += sizeof(struct sockaddr_atmsvc);	tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC);	if (!tmp_buf) {		spin_unlock_irqrestore(&dev->lock, flags);		return -ENOMEM;	}	list_for_each_entry(this, head, entry)	    memcpy(tmp_bufp++, &this->addr, sizeof(struct sockaddr_atmsvc));	spin_unlock_irqrestore(&dev->lock, flags);	error = total > size ? -E2BIG : total;	if (copy_to_user(buf, tmp_buf, total < size ? total : size))		error = -EFAULT;	kfree(tmp_buf);	return error;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -