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
);
39 static void notify_sigd(struct atm_dev
*dev
)
41 struct sockaddr_atmpvc pvc
;
43 pvc
.sap_addr
.itf
= dev
->number
;
44 sigd_enq(NULL
,as_itf_notify
,NULL
,&pvc
,NULL
);
48 void atm_reset_addr(struct atm_dev
*dev
)
51 struct atm_dev_addr
*this;
53 spin_lock_irqsave(&dev
->lock
, flags
);
56 dev
->local
= this->next
;
59 spin_unlock_irqrestore(&dev
->lock
, flags
);
64 int atm_add_addr(struct atm_dev
*dev
,struct sockaddr_atmsvc
*addr
)
67 struct atm_dev_addr
**walk
;
70 error
= check_addr(addr
);
73 spin_lock_irqsave(&dev
->lock
, flags
);
74 for (walk
= &dev
->local
; *walk
; walk
= &(*walk
)->next
)
75 if (identical(&(*walk
)->addr
,addr
)) {
76 spin_unlock_irqrestore(&dev
->lock
, flags
);
79 *walk
= kmalloc(sizeof(struct atm_dev_addr
), GFP_ATOMIC
);
81 spin_unlock_irqrestore(&dev
->lock
, flags
);
84 (*walk
)->addr
= *addr
;
86 spin_unlock_irqrestore(&dev
->lock
, flags
);
92 int atm_del_addr(struct atm_dev
*dev
,struct sockaddr_atmsvc
*addr
)
95 struct atm_dev_addr
**walk
,*this;
98 error
= check_addr(addr
);
101 spin_lock_irqsave(&dev
->lock
, flags
);
102 for (walk
= &dev
->local
; *walk
; walk
= &(*walk
)->next
)
103 if (identical(&(*walk
)->addr
,addr
)) break;
105 spin_unlock_irqrestore(&dev
->lock
, flags
);
111 spin_unlock_irqrestore(&dev
->lock
, flags
);
117 int atm_get_addr(struct atm_dev
*dev
,struct sockaddr_atmsvc
*u_buf
,int size
)
120 struct atm_dev_addr
*walk
;
121 int total
= 0, error
;
122 struct sockaddr_atmsvc
*tmp_buf
, *tmp_bufp
;
125 spin_lock_irqsave(&dev
->lock
, flags
);
126 for (walk
= dev
->local
; walk
; walk
= walk
->next
)
127 total
+= sizeof(struct sockaddr_atmsvc
);
128 tmp_buf
= tmp_bufp
= kmalloc(total
, GFP_ATOMIC
);
130 spin_unlock_irqrestore(&dev
->lock
, flags
);
133 for (walk
= dev
->local
; walk
; walk
= walk
->next
)
134 memcpy(tmp_bufp
++, &walk
->addr
, sizeof(struct sockaddr_atmsvc
));
135 spin_unlock_irqrestore(&dev
->lock
, flags
);
136 error
= total
> size
? -E2BIG
: total
;
137 if (copy_to_user(u_buf
, tmp_buf
, total
< size
? total
: size
))