1 /* net/atm/addr.c - Local ATM address registry */
3 /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
7 #include <linux/atmdev.h>
8 #include <linux/sched.h>
9 #include <asm/uaccess.h>
11 #include "signaling.h"
15 static int check_addr(struct sockaddr_atmsvc
*addr
)
19 if (addr
->sas_family
!= AF_ATMSVC
) return -EAFNOSUPPORT
;
20 if (!*addr
->sas_addr
.pub
)
21 return *addr
->sas_addr
.prv
? 0 : -EINVAL
;
22 for (i
= 1; i
< ATM_E164_LEN
+1; i
++) /* make sure it's \0-terminated */
23 if (!addr
->sas_addr
.pub
[i
]) return 0;
28 static int identical(struct sockaddr_atmsvc
*a
,struct sockaddr_atmsvc
*b
)
31 if (memcmp(a
->sas_addr
.prv
,b
->sas_addr
.prv
,ATM_ESA_LEN
))
33 if (!*a
->sas_addr
.pub
) return !*b
->sas_addr
.pub
;
34 if (!*b
->sas_addr
.pub
) return 0;
35 return !strcmp(a
->sas_addr
.pub
,b
->sas_addr
.pub
);
40 * Avoid modification of any list of local interfaces while reading it
41 * (which may involve page faults and therefore rescheduling)
44 static DECLARE_MUTEX(local_lock
);
45 extern spinlock_t atm_dev_lock
;
47 static void notify_sigd(struct atm_dev
*dev
)
49 struct sockaddr_atmpvc pvc
;
51 pvc
.sap_addr
.itf
= dev
->number
;
52 sigd_enq(NULL
,as_itf_notify
,NULL
,&pvc
,NULL
);
56 void reset_addr(struct atm_dev
*dev
)
58 struct atm_dev_addr
*this;
61 spin_lock (&atm_dev_lock
);
64 dev
->local
= this->next
;
68 spin_unlock (&atm_dev_lock
);
73 int add_addr(struct atm_dev
*dev
,struct sockaddr_atmsvc
*addr
)
75 struct atm_dev_addr
**walk
;
78 error
= check_addr(addr
);
79 if (error
) return error
;
81 for (walk
= &dev
->local
; *walk
; walk
= &(*walk
)->next
)
82 if (identical(&(*walk
)->addr
,addr
)) {
86 *walk
= kmalloc(sizeof(struct atm_dev_addr
),GFP_KERNEL
);
91 (*walk
)->addr
= *addr
;
99 int del_addr(struct atm_dev
*dev
,struct sockaddr_atmsvc
*addr
)
101 struct atm_dev_addr
**walk
,*this;
104 error
= check_addr(addr
);
105 if (error
) return error
;
107 for (walk
= &dev
->local
; *walk
; walk
= &(*walk
)->next
)
108 if (identical(&(*walk
)->addr
,addr
)) break;
122 int get_addr(struct atm_dev
*dev
,struct sockaddr_atmsvc
*u_buf
,int size
)
124 struct atm_dev_addr
*walk
;
129 for (walk
= dev
->local
; walk
; walk
= walk
->next
) {
130 total
+= sizeof(struct sockaddr_atmsvc
);
135 if (copy_to_user(u_buf
,&walk
->addr
,
136 sizeof(struct sockaddr_atmsvc
))) {