patch-2.3.15 linux/net/atm/addr.c
Next file: linux/net/atm/addr.h
Previous file: linux/net/atm/Makefile
Back to the patch index
Back to the overall index
- Lines: 166
- Date:
Mon Aug 23 09:56:32 1999
- Orig file:
v2.3.14/linux/net/atm/addr.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.3.14/linux/net/atm/addr.c linux/net/atm/addr.c
@@ -0,0 +1,165 @@
+/* net/atm/addr.c - Local ATM address registry */
+
+/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
+
+
+#include <linux/atm.h>
+#include <linux/atmdev.h>
+#include <linux/wait.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)
+ if (!*addr->sas_addr.prv) return -EINVAL;
+ else return 0;
+ 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);
+}
+
+
+/*
+ * Avoid modification of any list of local interfaces while reading it
+ * (which may involve page faults and therefore rescheduling)
+ */
+
+
+static volatile int local_lock = 0;
+static wait_queue_head_t local_wait;
+
+
+static void lock_local(void)
+{
+ while (local_lock) sleep_on(&local_wait);
+ local_lock = 1;
+}
+
+
+static void unlock_local(void)
+{
+ local_lock = 0;
+ wake_up(&local_wait);
+}
+
+
+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 reset_addr(struct atm_dev *dev)
+{
+ struct atm_dev_addr *this;
+
+ lock_local();
+ while (dev->local) {
+ this = dev->local;
+ dev->local = this->next;
+ kfree(this);
+ }
+ unlock_local();
+ notify_sigd(dev);
+}
+
+
+int add_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr)
+{
+ struct atm_dev_addr **walk;
+ int error;
+
+ error = check_addr(addr);
+ if (error) return error;
+ lock_local();
+ for (walk = &dev->local; *walk; walk = &(*walk)->next)
+ if (identical(&(*walk)->addr,addr)) {
+ unlock_local();
+ return -EEXIST;
+ }
+ *walk = kmalloc(sizeof(struct atm_dev_addr),GFP_KERNEL);
+ if (!*walk) {
+ unlock_local();
+ return -ENOMEM;
+ }
+ (*walk)->addr = *addr;
+ (*walk)->next = NULL;
+ unlock_local();
+ notify_sigd(dev);
+ return 0;
+}
+
+
+int del_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr)
+{
+ struct atm_dev_addr **walk,*this;
+ int error;
+
+ error = check_addr(addr);
+ if (error) return error;
+ lock_local();
+ for (walk = &dev->local; *walk; walk = &(*walk)->next)
+ if (identical(&(*walk)->addr,addr)) break;
+ if (!*walk) {
+ unlock_local();
+ return -ENOENT;
+ }
+ this = *walk;
+ *walk = this->next;
+ kfree(this);
+ unlock_local();
+ notify_sigd(dev);
+ return 0;
+}
+
+
+int get_addr(struct atm_dev *dev,struct sockaddr_atmsvc *u_buf,int size)
+{
+ struct atm_dev_addr *walk;
+ int total;
+
+ lock_local();
+ total = 0;
+ for (walk = dev->local; walk; walk = walk->next) {
+ total += sizeof(struct sockaddr_atmsvc);
+ if (total > size) {
+ unlock_local();
+ return -E2BIG;
+ }
+ if (copy_to_user(u_buf,&walk->addr,
+ sizeof(struct sockaddr_atmsvc))) {
+ unlock_local();
+ return -EFAULT;
+ }
+ u_buf++;
+ }
+ unlock_local();
+ return total;
+}
+
+
+void init_addr(void)
+{
+ init_waitqueue_head(&local_wait);
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)