Diff markup
1 /* net/atm/clip.c - RFC1577 Classical IP over 1 /* net/atm/clip.c - RFC1577 Classical IP over ATM */
2 2
3 /* Written 1995-2000 by Werner Almesberger, EP 3 /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4 4
5 <<
6 #include <linux/config.h> <<
7 #include <linux/string.h> 5 #include <linux/string.h>
8 #include <linux/errno.h> 6 #include <linux/errno.h>
9 #include <linux/kernel.h> /* for UINT_MAX */ 7 #include <linux/kernel.h> /* for UINT_MAX */
10 #include <linux/module.h> 8 #include <linux/module.h>
11 #include <linux/init.h> 9 #include <linux/init.h>
12 #include <linux/netdevice.h> 10 #include <linux/netdevice.h>
13 #include <linux/skbuff.h> 11 #include <linux/skbuff.h>
14 #include <linux/wait.h> 12 #include <linux/wait.h>
15 #include <linux/timer.h> 13 #include <linux/timer.h>
16 #include <linux/if_arp.h> /* for some manifest 14 #include <linux/if_arp.h> /* for some manifest constants */
17 #include <linux/notifier.h> 15 #include <linux/notifier.h>
18 #include <linux/atm.h> 16 #include <linux/atm.h>
19 #include <linux/atmdev.h> 17 #include <linux/atmdev.h>
20 #include <linux/atmclip.h> 18 #include <linux/atmclip.h>
21 #include <linux/atmarp.h> 19 #include <linux/atmarp.h>
>> 20 #include <linux/capability.h>
22 #include <linux/ip.h> /* for net/route.h */ 21 #include <linux/ip.h> /* for net/route.h */
23 #include <linux/in.h> /* for struct sockaddr_i 22 #include <linux/in.h> /* for struct sockaddr_in */
24 #include <linux/if.h> /* for IFF_UP */ 23 #include <linux/if.h> /* for IFF_UP */
25 #include <linux/inetdevice.h> 24 #include <linux/inetdevice.h>
26 #include <linux/bitops.h> 25 #include <linux/bitops.h>
>> 26 #include <linux/poison.h>
27 #include <linux/proc_fs.h> 27 #include <linux/proc_fs.h>
28 #include <linux/seq_file.h> 28 #include <linux/seq_file.h>
29 #include <linux/rcupdate.h> 29 #include <linux/rcupdate.h>
30 #include <linux/jhash.h> 30 #include <linux/jhash.h>
31 #include <net/route.h> /* for struct rtable an 31 #include <net/route.h> /* for struct rtable and routing */
32 #include <net/icmp.h> /* icmp_send */ 32 #include <net/icmp.h> /* icmp_send */
33 #include <asm/param.h> /* for HZ */ 33 #include <asm/param.h> /* for HZ */
34 #include <asm/byteorder.h> /* for htons etc. * 34 #include <asm/byteorder.h> /* for htons etc. */
35 #include <asm/system.h> /* save/restore_flags 35 #include <asm/system.h> /* save/restore_flags */
36 #include <asm/uaccess.h> 36 #include <asm/uaccess.h>
37 #include <asm/atomic.h> 37 #include <asm/atomic.h>
38 38
39 #include "common.h" 39 #include "common.h"
40 #include "resources.h" 40 #include "resources.h"
41 #include "ipcommon.h" <<
42 #include <net/atmclip.h> 41 #include <net/atmclip.h>
43 42
44 <<
45 #if 0 <<
46 #define DPRINTK(format,args...) printk(format, <<
47 #else <<
48 #define DPRINTK(format,args...) <<
49 #endif <<
50 <<
51 <<
52 static struct net_device *clip_devs; 43 static struct net_device *clip_devs;
53 static struct atm_vcc *atmarpd; 44 static struct atm_vcc *atmarpd;
54 static struct neigh_table clip_tbl; 45 static struct neigh_table clip_tbl;
55 static struct timer_list idle_timer; 46 static struct timer_list idle_timer;
56 static int start_timer = 1; <<
57 47
58 !! 48 static int to_atmarpd(enum atmarp_ctrl_type type, int itf, __be32 ip)
59 static int to_atmarpd(enum atmarp_ctrl_type ty <<
60 { 49 {
>> 50 struct sock *sk;
61 struct atmarp_ctrl *ctrl; 51 struct atmarp_ctrl *ctrl;
62 struct sk_buff *skb; 52 struct sk_buff *skb;
63 53
64 DPRINTK("to_atmarpd(%d)\n",type); !! 54 pr_debug("to_atmarpd(%d)\n", type);
65 if (!atmarpd) return -EUNATCH; !! 55 if (!atmarpd)
>> 56 return -EUNATCH;
66 skb = alloc_skb(sizeof(struct atmarp_c 57 skb = alloc_skb(sizeof(struct atmarp_ctrl),GFP_ATOMIC);
67 if (!skb) return -ENOMEM; !! 58 if (!skb)
>> 59 return -ENOMEM;
68 ctrl = (struct atmarp_ctrl *) skb_put( 60 ctrl = (struct atmarp_ctrl *) skb_put(skb,sizeof(struct atmarp_ctrl));
69 ctrl->type = type; 61 ctrl->type = type;
70 ctrl->itf_num = itf; 62 ctrl->itf_num = itf;
71 ctrl->ip = ip; 63 ctrl->ip = ip;
72 atm_force_charge(atmarpd,skb->truesize !! 64 atm_force_charge(atmarpd, skb->truesize);
73 skb_queue_tail(&atmarpd->sk->sk_receiv !! 65
74 atmarpd->sk->sk_data_ready(atmarpd->sk !! 66 sk = sk_atm(atmarpd);
>> 67 skb_queue_tail(&sk->sk_receive_queue, skb);
>> 68 sk->sk_data_ready(sk, skb->len);
75 return 0; 69 return 0;
76 } 70 }
77 71
78 !! 72 static void link_vcc(struct clip_vcc *clip_vcc, struct atmarp_entry *entry)
79 static void link_vcc(struct clip_vcc *clip_vcc <<
80 { 73 {
81 DPRINTK("link_vcc %p to entry %p (neig !! 74 pr_debug("link_vcc %p to entry %p (neigh %p)\n", clip_vcc, entry,
82 entry->neigh); !! 75 entry->neigh);
83 clip_vcc->entry = entry; 76 clip_vcc->entry = entry;
84 clip_vcc->xoff = 0; /* @@@ may overrun !! 77 clip_vcc->xoff = 0; /* @@@ may overrun buffer by one packet */
85 clip_vcc->next = entry->vccs; 78 clip_vcc->next = entry->vccs;
86 entry->vccs = clip_vcc; 79 entry->vccs = clip_vcc;
87 entry->neigh->used = jiffies; 80 entry->neigh->used = jiffies;
88 } 81 }
89 82
90 <<
91 static void unlink_clip_vcc(struct clip_vcc *c 83 static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
92 { 84 {
93 struct atmarp_entry *entry = clip_vcc- 85 struct atmarp_entry *entry = clip_vcc->entry;
94 struct clip_vcc **walk; 86 struct clip_vcc **walk;
95 87
96 if (!entry) { 88 if (!entry) {
97 printk(KERN_CRIT "!clip_vcc->e !! 89 printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n", clip_vcc);
98 return; 90 return;
99 } 91 }
100 spin_lock_bh(&entry->neigh->dev->xmit_ !! 92 netif_tx_lock_bh(entry->neigh->dev); /* block clip_start_xmit() */
101 entry->neigh->used = jiffies; 93 entry->neigh->used = jiffies;
102 for (walk = &entry->vccs; *walk; walk 94 for (walk = &entry->vccs; *walk; walk = &(*walk)->next)
103 if (*walk == clip_vcc) { 95 if (*walk == clip_vcc) {
104 int error; 96 int error;
105 97
106 *walk = clip_vcc->next !! 98 *walk = clip_vcc->next; /* atomic */
107 clip_vcc->entry = NULL 99 clip_vcc->entry = NULL;
108 if (clip_vcc->xoff) 100 if (clip_vcc->xoff)
109 netif_wake_que 101 netif_wake_queue(entry->neigh->dev);
110 if (entry->vccs) 102 if (entry->vccs)
111 goto out; 103 goto out;
112 entry->expires = jiffi !! 104 entry->expires = jiffies - 1;
113 /* force resol !! 105 /* force resolution or expiration */
114 error = neigh_update(e 106 error = neigh_update(entry->neigh, NULL, NUD_NONE,
115 N 107 NEIGH_UPDATE_F_ADMIN);
116 if (error) 108 if (error)
117 printk(KERN_CR 109 printk(KERN_CRIT "unlink_clip_vcc: "
118 "neigh_upd !! 110 "neigh_update failed with %d\n", error);
119 goto out; 111 goto out;
120 } 112 }
121 printk(KERN_CRIT "ATMARP: unlink_clip_ 113 printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc "
122 "0x%p)\n",entry,clip_vcc); !! 114 "0x%p)\n", entry, clip_vcc);
123 out: !! 115 out:
124 spin_unlock_bh(&entry->neigh->dev->xmi !! 116 netif_tx_unlock_bh(entry->neigh->dev);
125 } 117 }
126 118
127 /* The neighbour entry n->lock is held. */ 119 /* The neighbour entry n->lock is held. */
128 static int neigh_check_cb(struct neighbour *n) 120 static int neigh_check_cb(struct neighbour *n)
129 { 121 {
130 struct atmarp_entry *entry = NEIGH2ENT 122 struct atmarp_entry *entry = NEIGH2ENTRY(n);
131 struct clip_vcc *cv; 123 struct clip_vcc *cv;
132 124
133 for (cv = entry->vccs; cv; cv = cv->ne 125 for (cv = entry->vccs; cv; cv = cv->next) {
134 unsigned long exp = cv->last_u 126 unsigned long exp = cv->last_use + cv->idle_timeout;
135 127
136 if (cv->idle_timeout && time_a 128 if (cv->idle_timeout && time_after(jiffies, exp)) {
137 DPRINTK("releasing vcc !! 129 pr_debug("releasing vcc %p->%p of entry %p\n",
138 cv, cv->vcc, e 130 cv, cv->vcc, entry);
139 vcc_release_async(cv-> 131 vcc_release_async(cv->vcc, -ETIMEDOUT);
140 } 132 }
141 } 133 }
142 134
143 if (entry->vccs || time_before(jiffies 135 if (entry->vccs || time_before(jiffies, entry->expires))
144 return 0; 136 return 0;
145 137
146 if (atomic_read(&n->refcnt) > 1) { 138 if (atomic_read(&n->refcnt) > 1) {
147 struct sk_buff *skb; 139 struct sk_buff *skb;
148 140
149 DPRINTK("destruction postponed !! 141 pr_debug("destruction postponed with ref %d\n",
150 atomic_read(&n->refcnt 142 atomic_read(&n->refcnt));
151 143
152 while ((skb = skb_dequeue(&n-> !! 144 while ((skb = skb_dequeue(&n->arp_queue)) != NULL)
153 dev_kfree_skb(skb); 145 dev_kfree_skb(skb);
154 146
155 return 0; 147 return 0;
156 } 148 }
157 149
158 DPRINTK("expired neigh %p\n",n); !! 150 pr_debug("expired neigh %p\n", n);
159 return 1; 151 return 1;
160 } 152 }
161 153
162 static void idle_timer_check(unsigned long dum 154 static void idle_timer_check(unsigned long dummy)
163 { 155 {
164 write_lock(&clip_tbl.lock); 156 write_lock(&clip_tbl.lock);
165 __neigh_for_each_release(&clip_tbl, ne 157 __neigh_for_each_release(&clip_tbl, neigh_check_cb);
166 mod_timer(&idle_timer, jiffies+CLIP_CH !! 158 mod_timer(&idle_timer, jiffies + CLIP_CHECK_INTERVAL * HZ);
167 write_unlock(&clip_tbl.lock); 159 write_unlock(&clip_tbl.lock);
168 } 160 }
169 161
170 static int clip_arp_rcv(struct sk_buff *skb) 162 static int clip_arp_rcv(struct sk_buff *skb)
171 { 163 {
172 struct atm_vcc *vcc; 164 struct atm_vcc *vcc;
173 165
174 DPRINTK("clip_arp_rcv\n"); !! 166 pr_debug("clip_arp_rcv\n");
175 vcc = ATM_SKB(skb)->vcc; 167 vcc = ATM_SKB(skb)->vcc;
176 if (!vcc || !atm_charge(vcc,skb->trues !! 168 if (!vcc || !atm_charge(vcc, skb->truesize)) {
177 dev_kfree_skb_any(skb); 169 dev_kfree_skb_any(skb);
178 return 0; 170 return 0;
179 } 171 }
180 DPRINTK("pushing to %p\n",vcc); !! 172 pr_debug("pushing to %p\n", vcc);
181 DPRINTK("using %p\n",CLIP_VCC(vcc)->ol !! 173 pr_debug("using %p\n", CLIP_VCC(vcc)->old_push);
182 CLIP_VCC(vcc)->old_push(vcc,skb); !! 174 CLIP_VCC(vcc)->old_push(vcc, skb);
183 return 0; 175 return 0;
184 } 176 }
185 177
186 static const unsigned char llc_oui[] = { 178 static const unsigned char llc_oui[] = {
187 0xaa, /* DSAP: non-ISO */ 179 0xaa, /* DSAP: non-ISO */
188 0xaa, /* SSAP: non-ISO */ 180 0xaa, /* SSAP: non-ISO */
189 0x03, /* Ctrl: Unnumbered Informatio 181 0x03, /* Ctrl: Unnumbered Information Command PDU */
190 0x00, /* OUI: EtherType */ 182 0x00, /* OUI: EtherType */
191 0x00, 183 0x00,
192 0x00 }; !! 184 0x00
>> 185 };
193 186
194 static void clip_push(struct atm_vcc *vcc,stru !! 187 static void clip_push(struct atm_vcc *vcc, struct sk_buff *skb)
195 { 188 {
196 struct clip_vcc *clip_vcc = CLIP_VCC(v 189 struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
197 190
198 DPRINTK("clip push\n"); !! 191 pr_debug("clip push\n");
199 if (!skb) { 192 if (!skb) {
200 DPRINTK("removing VCC %p\n",cl !! 193 pr_debug("removing VCC %p\n", clip_vcc);
201 if (clip_vcc->entry) unlink_cl !! 194 if (clip_vcc->entry)
202 clip_vcc->old_push(vcc,NULL); !! 195 unlink_clip_vcc(clip_vcc);
>> 196 clip_vcc->old_push(vcc, NULL); /* pass on the bad news */
203 kfree(clip_vcc); 197 kfree(clip_vcc);
204 return; 198 return;
205 } 199 }
206 atm_return(vcc,skb->truesize); !! 200 atm_return(vcc, skb->truesize);
207 skb->dev = clip_vcc->entry ? clip_vcc- 201 skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs;
208 /* clip_vcc->entry == NULL if !! 202 /* clip_vcc->entry == NULL if we don't have an IP address yet */
209 if (!skb->dev) { 203 if (!skb->dev) {
210 dev_kfree_skb_any(skb); 204 dev_kfree_skb_any(skb);
211 return; 205 return;
212 } 206 }
213 ATM_SKB(skb)->vcc = vcc; 207 ATM_SKB(skb)->vcc = vcc;
214 skb->mac.raw = skb->data; !! 208 skb_reset_mac_header(skb);
215 if (!clip_vcc->encap || skb->len < RFC !! 209 if (!clip_vcc->encap
216 llc_oui,sizeof(llc_oui))) skb->pro !! 210 || skb->len < RFC1483LLC_LEN
>> 211 || memcmp(skb->data, llc_oui, sizeof (llc_oui)))
>> 212 skb->protocol = htons(ETH_P_IP);
217 else { 213 else {
218 skb->protocol = ((u16 *) skb-> !! 214 skb->protocol = ((__be16 *) skb->data)[3];
219 skb_pull(skb,RFC1483LLC_LEN); !! 215 skb_pull(skb, RFC1483LLC_LEN);
220 if (skb->protocol == htons(ETH 216 if (skb->protocol == htons(ETH_P_ARP)) {
221 PRIV(skb->dev)->stats. 217 PRIV(skb->dev)->stats.rx_packets++;
222 PRIV(skb->dev)->stats. 218 PRIV(skb->dev)->stats.rx_bytes += skb->len;
223 clip_arp_rcv(skb); 219 clip_arp_rcv(skb);
224 return; 220 return;
225 } 221 }
226 } 222 }
227 clip_vcc->last_use = jiffies; 223 clip_vcc->last_use = jiffies;
228 PRIV(skb->dev)->stats.rx_packets++; 224 PRIV(skb->dev)->stats.rx_packets++;
229 PRIV(skb->dev)->stats.rx_bytes += skb- 225 PRIV(skb->dev)->stats.rx_bytes += skb->len;
230 memset(ATM_SKB(skb), 0, sizeof(struct 226 memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
231 netif_rx(skb); 227 netif_rx(skb);
232 } 228 }
233 229
234 <<
235 /* 230 /*
236 * Note: these spinlocks _must_not_ block on n 231 * Note: these spinlocks _must_not_ block on non-SMP. The only goal is that
237 * clip_pop is atomic with respect to the crit 232 * clip_pop is atomic with respect to the critical section in clip_start_xmit.
238 */ 233 */
239 234
240 !! 235 static void clip_pop(struct atm_vcc *vcc, struct sk_buff *skb)
241 static void clip_pop(struct atm_vcc *vcc,struc <<
242 { 236 {
243 struct clip_vcc *clip_vcc = CLIP_VCC(v 237 struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
244 struct net_device *dev = skb->dev; 238 struct net_device *dev = skb->dev;
245 int old; 239 int old;
246 unsigned long flags; 240 unsigned long flags;
247 241
248 DPRINTK("clip_pop(vcc %p)\n",vcc); !! 242 pr_debug("clip_pop(vcc %p)\n", vcc);
249 clip_vcc->old_pop(vcc,skb); !! 243 clip_vcc->old_pop(vcc, skb);
250 /* skb->dev == NULL in outbound ARP pa 244 /* skb->dev == NULL in outbound ARP packets */
251 if (!dev) return; !! 245 if (!dev)
252 spin_lock_irqsave(&PRIV(dev)->xoff_loc !! 246 return;
253 if (atm_may_send(vcc,0)) { !! 247 spin_lock_irqsave(&PRIV(dev)->xoff_lock, flags);
254 old = xchg(&clip_vcc->xoff,0); !! 248 if (atm_may_send(vcc, 0)) {
255 if (old) netif_wake_queue(dev) !! 249 old = xchg(&clip_vcc->xoff, 0);
>> 250 if (old)
>> 251 netif_wake_queue(dev);
256 } 252 }
257 spin_unlock_irqrestore(&PRIV(dev)->xof !! 253 spin_unlock_irqrestore(&PRIV(dev)->xoff_lock, flags);
258 } 254 }
259 255
260 !! 256 static void clip_neigh_solicit(struct neighbour *neigh, struct sk_buff *skb)
261 static void clip_neigh_destroy(struct neighbou <<
262 { <<
263 DPRINTK("clip_neigh_destroy (neigh %p) <<
264 if (NEIGH2ENTRY(neigh)->vccs) <<
265 printk(KERN_CRIT "clip_neigh_d <<
266 NEIGH2ENTRY(neigh)->vccs = (void *) 0x <<
267 } <<
268 <<
269 <<
270 static void clip_neigh_solicit(struct neighbou <<
271 { 257 {
272 DPRINTK("clip_neigh_solicit (neigh %p, !! 258 pr_debug("clip_neigh_solicit (neigh %p, skb %p)\n", neigh, skb);
273 to_atmarpd(act_need,PRIV(neigh->dev)-> !! 259 to_atmarpd(act_need, PRIV(neigh->dev)->number, NEIGH2ENTRY(neigh)->ip);
274 } 260 }
275 261
276 !! 262 static void clip_neigh_error(struct neighbour *neigh, struct sk_buff *skb)
277 static void clip_neigh_error(struct neighbour <<
278 { 263 {
279 #ifndef CONFIG_ATM_CLIP_NO_ICMP 264 #ifndef CONFIG_ATM_CLIP_NO_ICMP
280 icmp_send(skb,ICMP_DEST_UNREACH,ICMP_H !! 265 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
281 #endif 266 #endif
282 kfree_skb(skb); 267 kfree_skb(skb);
283 } 268 }
284 269
285 <<
286 static struct neigh_ops clip_neigh_ops = { 270 static struct neigh_ops clip_neigh_ops = {
287 .family = AF_INET, 271 .family = AF_INET,
288 .destructor = clip_neigh_des <<
289 .solicit = clip_neigh_sol 272 .solicit = clip_neigh_solicit,
290 .error_report = clip_neigh_err 273 .error_report = clip_neigh_error,
291 .output = dev_queue_xmit 274 .output = dev_queue_xmit,
292 .connected_output = dev_queue_xmit 275 .connected_output = dev_queue_xmit,
293 .hh_output = dev_queue_xmit 276 .hh_output = dev_queue_xmit,
294 .queue_xmit = dev_queue_xmit 277 .queue_xmit = dev_queue_xmit,
295 }; 278 };
296 279
297 <<
298 static int clip_constructor(struct neighbour * 280 static int clip_constructor(struct neighbour *neigh)
299 { 281 {
300 struct atmarp_entry *entry = NEIGH2ENT 282 struct atmarp_entry *entry = NEIGH2ENTRY(neigh);
301 struct net_device *dev = neigh->dev; 283 struct net_device *dev = neigh->dev;
302 struct in_device *in_dev; 284 struct in_device *in_dev;
303 struct neigh_parms *parms; 285 struct neigh_parms *parms;
304 286
305 DPRINTK("clip_constructor (neigh %p, e !! 287 pr_debug("clip_constructor (neigh %p, entry %p)\n", neigh, entry);
306 neigh->type = inet_addr_type(entry->ip !! 288 neigh->type = inet_addr_type(&init_net, entry->ip);
307 if (neigh->type != RTN_UNICAST) return !! 289 if (neigh->type != RTN_UNICAST)
>> 290 return -EINVAL;
308 291
309 rcu_read_lock(); 292 rcu_read_lock();
310 in_dev = rcu_dereference(__in_dev_get( !! 293 in_dev = __in_dev_get_rcu(dev);
311 if (!in_dev) { 294 if (!in_dev) {
312 rcu_read_unlock(); 295 rcu_read_unlock();
313 return -EINVAL; 296 return -EINVAL;
314 } 297 }
315 298
316 parms = in_dev->arp_parms; 299 parms = in_dev->arp_parms;
317 __neigh_parms_put(neigh->parms); 300 __neigh_parms_put(neigh->parms);
318 neigh->parms = neigh_parms_clone(parms 301 neigh->parms = neigh_parms_clone(parms);
319 rcu_read_unlock(); 302 rcu_read_unlock();
320 303
321 neigh->ops = &clip_neigh_ops; 304 neigh->ops = &clip_neigh_ops;
322 neigh->output = neigh->nud_state & NUD 305 neigh->output = neigh->nud_state & NUD_VALID ?
323 neigh->ops->connected_output : nei 306 neigh->ops->connected_output : neigh->ops->output;
324 entry->neigh = neigh; 307 entry->neigh = neigh;
325 entry->vccs = NULL; 308 entry->vccs = NULL;
326 entry->expires = jiffies-1; !! 309 entry->expires = jiffies - 1;
327 return 0; 310 return 0;
328 } 311 }
329 312
330 static u32 clip_hash(const void *pkey, const s 313 static u32 clip_hash(const void *pkey, const struct net_device *dev)
331 { 314 {
332 return jhash_2words(*(u32 *)pkey, dev- !! 315 return jhash_2words(*(u32 *) pkey, dev->ifindex, clip_tbl.hash_rnd);
333 } 316 }
334 317
335 static struct neigh_table clip_tbl = { 318 static struct neigh_table clip_tbl = {
336 .family = AF_INET, 319 .family = AF_INET,
337 .entry_size = sizeof(struct neighb 320 .entry_size = sizeof(struct neighbour)+sizeof(struct atmarp_entry),
338 .key_len = 4, 321 .key_len = 4,
339 .hash = clip_hash, 322 .hash = clip_hash,
340 .constructor = clip_constructor, 323 .constructor = clip_constructor,
341 .id = "clip_arp_cache", 324 .id = "clip_arp_cache",
342 325
343 /* parameters are copied from ARP ... 326 /* parameters are copied from ARP ... */
344 .parms = { 327 .parms = {
345 .tbl = &cli 328 .tbl = &clip_tbl,
346 .base_reachable_time = 30 * 329 .base_reachable_time = 30 * HZ,
347 .retrans_time = 1 * 330 .retrans_time = 1 * HZ,
348 .gc_staletime = 60 * 331 .gc_staletime = 60 * HZ,
349 .reachable_time = 30 * 332 .reachable_time = 30 * HZ,
350 .delay_probe_time = 5 * 333 .delay_probe_time = 5 * HZ,
351 .queue_len = 3, 334 .queue_len = 3,
352 .ucast_probes = 3, 335 .ucast_probes = 3,
353 .mcast_probes = 3, 336 .mcast_probes = 3,
354 .anycast_delay = 1 * 337 .anycast_delay = 1 * HZ,
355 .proxy_delay = (8 * 338 .proxy_delay = (8 * HZ) / 10,
356 .proxy_qlen = 64, 339 .proxy_qlen = 64,
357 .locktime = 1 * 340 .locktime = 1 * HZ,
358 }, 341 },
359 .gc_interval = 30 * HZ, 342 .gc_interval = 30 * HZ,
360 .gc_thresh1 = 128, 343 .gc_thresh1 = 128,
361 .gc_thresh2 = 512, 344 .gc_thresh2 = 512,
362 .gc_thresh3 = 1024, 345 .gc_thresh3 = 1024,
363 }; 346 };
364 347
365 <<
366 /* @@@ copy bh locking from arp.c -- need to b 348 /* @@@ copy bh locking from arp.c -- need to bh-enable atm code before */
367 349
368 /* 350 /*
369 * We play with the resolve flag: 0 and 1 have 351 * We play with the resolve flag: 0 and 1 have the usual meaning, but -1 means
370 * to allocate the neighbour entry but not to 352 * to allocate the neighbour entry but not to ask atmarpd for resolution. Also,
371 * don't increment the usage count. This is us 353 * don't increment the usage count. This is used to create entries in
372 * clip_setentry. 354 * clip_setentry.
373 */ 355 */
374 356
375 !! 357 static int clip_encap(struct atm_vcc *vcc, int mode)
376 static int clip_encap(struct atm_vcc *vcc,int <<
377 { 358 {
378 CLIP_VCC(vcc)->encap = mode; 359 CLIP_VCC(vcc)->encap = mode;
379 return 0; 360 return 0;
380 } 361 }
381 362
382 !! 363 static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev)
383 static int clip_start_xmit(struct sk_buff *skb <<
384 { 364 {
385 struct clip_priv *clip_priv = PRIV(dev 365 struct clip_priv *clip_priv = PRIV(dev);
386 struct atmarp_entry *entry; 366 struct atmarp_entry *entry;
387 struct atm_vcc *vcc; 367 struct atm_vcc *vcc;
388 int old; 368 int old;
389 unsigned long flags; 369 unsigned long flags;
390 370
391 DPRINTK("clip_start_xmit (skb %p)\n",s !! 371 pr_debug("clip_start_xmit (skb %p)\n", skb);
392 if (!skb->dst) { 372 if (!skb->dst) {
393 printk(KERN_ERR "clip_start_xm 373 printk(KERN_ERR "clip_start_xmit: skb->dst == NULL\n");
394 dev_kfree_skb(skb); 374 dev_kfree_skb(skb);
395 clip_priv->stats.tx_dropped++; 375 clip_priv->stats.tx_dropped++;
396 return 0; 376 return 0;
397 } 377 }
398 if (!skb->dst->neighbour) { 378 if (!skb->dst->neighbour) {
399 #if 0 379 #if 0
400 skb->dst->neighbour = clip_fin !! 380 skb->dst->neighbour = clip_find_neighbour(skb->dst, 1);
401 if (!skb->dst->neighbour) { 381 if (!skb->dst->neighbour) {
402 dev_kfree_skb(skb); /* !! 382 dev_kfree_skb(skb); /* lost that one */
403 clip_priv->stats.tx_dr 383 clip_priv->stats.tx_dropped++;
404 return 0; 384 return 0;
405 } 385 }
406 #endif 386 #endif
407 printk(KERN_ERR "clip_start_xm 387 printk(KERN_ERR "clip_start_xmit: NO NEIGHBOUR !\n");
408 dev_kfree_skb(skb); 388 dev_kfree_skb(skb);
409 clip_priv->stats.tx_dropped++; 389 clip_priv->stats.tx_dropped++;
410 return 0; 390 return 0;
411 } 391 }
412 entry = NEIGH2ENTRY(skb->dst->neighbou 392 entry = NEIGH2ENTRY(skb->dst->neighbour);
413 if (!entry->vccs) { 393 if (!entry->vccs) {
414 if (time_after(jiffies, entry- 394 if (time_after(jiffies, entry->expires)) {
415 /* should be resolved 395 /* should be resolved */
416 entry->expires = jiffi !! 396 entry->expires = jiffies + ATMARP_RETRY_DELAY * HZ;
417 to_atmarpd(act_need,PR !! 397 to_atmarpd(act_need, PRIV(dev)->number, entry->ip);
418 } 398 }
419 if (entry->neigh->arp_queue.ql 399 if (entry->neigh->arp_queue.qlen < ATMARP_MAX_UNRES_PACKETS)
420 skb_queue_tail(&entry- !! 400 skb_queue_tail(&entry->neigh->arp_queue, skb);
421 else { 401 else {
422 dev_kfree_skb(skb); 402 dev_kfree_skb(skb);
423 clip_priv->stats.tx_dr 403 clip_priv->stats.tx_dropped++;
424 } 404 }
425 return 0; 405 return 0;
426 } 406 }
427 DPRINTK("neigh %p, vccs %p\n",entry,en !! 407 pr_debug("neigh %p, vccs %p\n", entry, entry->vccs);
428 ATM_SKB(skb)->vcc = vcc = entry->vccs- 408 ATM_SKB(skb)->vcc = vcc = entry->vccs->vcc;
429 DPRINTK("using neighbour %p, vcc %p\n" !! 409 pr_debug("using neighbour %p, vcc %p\n", skb->dst->neighbour, vcc);
430 if (entry->vccs->encap) { 410 if (entry->vccs->encap) {
431 void *here; 411 void *here;
432 412
433 here = skb_push(skb,RFC1483LLC !! 413 here = skb_push(skb, RFC1483LLC_LEN);
434 memcpy(here,llc_oui,sizeof(llc !! 414 memcpy(here, llc_oui, sizeof(llc_oui));
435 ((u16 *) here)[3] = skb->proto !! 415 ((__be16 *) here)[3] = skb->protocol;
436 } 416 }
437 atomic_add(skb->truesize, &vcc->sk->sk !! 417 atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
438 ATM_SKB(skb)->atm_options = vcc->atm_o 418 ATM_SKB(skb)->atm_options = vcc->atm_options;
439 entry->vccs->last_use = jiffies; 419 entry->vccs->last_use = jiffies;
440 DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p) !! 420 pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, vcc, vcc->dev);
441 old = xchg(&entry->vccs->xoff,1); /* a !! 421 old = xchg(&entry->vccs->xoff, 1); /* assume XOFF ... */
442 if (old) { 422 if (old) {
443 printk(KERN_WARNING "clip_star 423 printk(KERN_WARNING "clip_start_xmit: XOFF->XOFF transition\n");
444 return 0; 424 return 0;
445 } 425 }
446 clip_priv->stats.tx_packets++; 426 clip_priv->stats.tx_packets++;
447 clip_priv->stats.tx_bytes += skb->len; 427 clip_priv->stats.tx_bytes += skb->len;
448 (void) vcc->send(vcc,skb); !! 428 vcc->send(vcc, skb);
449 if (atm_may_send(vcc,0)) { !! 429 if (atm_may_send(vcc, 0)) {
450 entry->vccs->xoff = 0; 430 entry->vccs->xoff = 0;
451 return 0; 431 return 0;
452 } 432 }
453 spin_lock_irqsave(&clip_priv->xoff_loc !! 433 spin_lock_irqsave(&clip_priv->xoff_lock, flags);
454 netif_stop_queue(dev); /* XOFF -> thro !! 434 netif_stop_queue(dev); /* XOFF -> throttle immediately */
455 barrier(); 435 barrier();
456 if (!entry->vccs->xoff) 436 if (!entry->vccs->xoff)
457 netif_start_queue(dev); 437 netif_start_queue(dev);
458 /* Oh, we just raced with clip !! 438 /* Oh, we just raced with clip_pop. netif_start_queue should be
459 good enough, because nothin !! 439 good enough, because nothing should really be asleep because
460 of the brief netif_stop_que !! 440 of the brief netif_stop_queue. If this isn't true or if it
461 changes, use netif_wake_que !! 441 changes, use netif_wake_queue instead. */
462 spin_unlock_irqrestore(&clip_priv->xof !! 442 spin_unlock_irqrestore(&clip_priv->xoff_lock, flags);
463 return 0; 443 return 0;
464 } 444 }
465 445
466 <<
467 static struct net_device_stats *clip_get_stats 446 static struct net_device_stats *clip_get_stats(struct net_device *dev)
468 { 447 {
469 return &PRIV(dev)->stats; 448 return &PRIV(dev)->stats;
470 } 449 }
471 450
472 !! 451 static int clip_mkip(struct atm_vcc *vcc, int timeout)
473 static int clip_mkip(struct atm_vcc *vcc,int t <<
474 { 452 {
475 struct clip_vcc *clip_vcc; 453 struct clip_vcc *clip_vcc;
476 struct sk_buff_head copy; <<
477 struct sk_buff *skb; 454 struct sk_buff *skb;
>> 455 struct sk_buff_head *rq;
>> 456 unsigned long flags;
478 457
479 if (!vcc->push) return -EBADFD; !! 458 if (!vcc->push)
480 clip_vcc = kmalloc(sizeof(struct clip_ !! 459 return -EBADFD;
481 if (!clip_vcc) return -ENOMEM; !! 460 clip_vcc = kmalloc(sizeof(struct clip_vcc), GFP_KERNEL);
482 DPRINTK("mkip clip_vcc %p vcc %p\n",cl !! 461 if (!clip_vcc)
>> 462 return -ENOMEM;
>> 463 pr_debug("mkip clip_vcc %p vcc %p\n", clip_vcc, vcc);
483 clip_vcc->vcc = vcc; 464 clip_vcc->vcc = vcc;
484 vcc->user_back = clip_vcc; 465 vcc->user_back = clip_vcc;
485 set_bit(ATM_VF_IS_CLIP, &vcc->flags); 466 set_bit(ATM_VF_IS_CLIP, &vcc->flags);
486 clip_vcc->entry = NULL; 467 clip_vcc->entry = NULL;
487 clip_vcc->xoff = 0; 468 clip_vcc->xoff = 0;
488 clip_vcc->encap = 1; 469 clip_vcc->encap = 1;
489 clip_vcc->last_use = jiffies; 470 clip_vcc->last_use = jiffies;
490 clip_vcc->idle_timeout = timeout*HZ; !! 471 clip_vcc->idle_timeout = timeout * HZ;
491 clip_vcc->old_push = vcc->push; 472 clip_vcc->old_push = vcc->push;
492 clip_vcc->old_pop = vcc->pop; 473 clip_vcc->old_pop = vcc->pop;
493 vcc->push = clip_push; 474 vcc->push = clip_push;
494 vcc->pop = clip_pop; 475 vcc->pop = clip_pop;
495 skb_queue_head_init(©); !! 476
496 skb_migrate(&vcc->sk->sk_receive_queue !! 477 rq = &sk_atm(vcc)->sk_receive_queue;
>> 478
>> 479 spin_lock_irqsave(&rq->lock, flags);
>> 480 if (skb_queue_empty(rq)) {
>> 481 skb = NULL;
>> 482 } else {
>> 483 /* NULL terminate the list. */
>> 484 rq->prev->next = NULL;
>> 485 skb = rq->next;
>> 486 }
>> 487 rq->prev = rq->next = (struct sk_buff *)rq;
>> 488 rq->qlen = 0;
>> 489 spin_unlock_irqrestore(&rq->lock, flags);
>> 490
497 /* re-process everything received betw 491 /* re-process everything received between connection setup and MKIP */
498 while ((skb = skb_dequeue(©)) != N !! 492 while (skb) {
>> 493 struct sk_buff *next = skb->next;
>> 494
>> 495 skb->next = skb->prev = NULL;
499 if (!clip_devs) { 496 if (!clip_devs) {
500 atm_return(vcc,skb->tr !! 497 atm_return(vcc, skb->truesize);
501 kfree_skb(skb); 498 kfree_skb(skb);
502 } !! 499 } else {
503 else { <<
504 unsigned int len = skb 500 unsigned int len = skb->len;
505 501
506 clip_push(vcc,skb); !! 502 skb_get(skb);
>> 503 clip_push(vcc, skb);
507 PRIV(skb->dev)->stats. 504 PRIV(skb->dev)->stats.rx_packets--;
508 PRIV(skb->dev)->stats. 505 PRIV(skb->dev)->stats.rx_bytes -= len;
>> 506 kfree_skb(skb);
509 } 507 }
>> 508
>> 509 skb = next;
>> 510 }
510 return 0; 511 return 0;
511 } 512 }
512 513
513 !! 514 static int clip_setentry(struct atm_vcc *vcc, __be32 ip)
514 static int clip_setentry(struct atm_vcc *vcc,u <<
515 { 515 {
516 struct neighbour *neigh; 516 struct neighbour *neigh;
517 struct atmarp_entry *entry; 517 struct atmarp_entry *entry;
518 int error; 518 int error;
519 struct clip_vcc *clip_vcc; 519 struct clip_vcc *clip_vcc;
520 struct flowi fl = { .nl_u = { .ip4_u = !! 520 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1}} };
521 struct rtable *rt; 521 struct rtable *rt;
522 522
523 if (vcc->push != clip_push) { 523 if (vcc->push != clip_push) {
524 printk(KERN_WARNING "clip_sete 524 printk(KERN_WARNING "clip_setentry: non-CLIP VCC\n");
525 return -EBADF; 525 return -EBADF;
526 } 526 }
527 clip_vcc = CLIP_VCC(vcc); 527 clip_vcc = CLIP_VCC(vcc);
528 if (!ip) { 528 if (!ip) {
529 if (!clip_vcc->entry) { 529 if (!clip_vcc->entry) {
530 printk(KERN_ERR "hidin 530 printk(KERN_ERR "hiding hidden ATMARP entry\n");
531 return 0; 531 return 0;
532 } 532 }
533 DPRINTK("setentry: remove\n"); !! 533 pr_debug("setentry: remove\n");
534 unlink_clip_vcc(clip_vcc); 534 unlink_clip_vcc(clip_vcc);
535 return 0; 535 return 0;
536 } 536 }
537 error = ip_route_output_key(&rt,&fl); !! 537 error = ip_route_output_key(&init_net, &rt, &fl);
538 if (error) return error; !! 538 if (error)
539 neigh = __neigh_lookup(&clip_tbl,&ip,r !! 539 return error;
>> 540 neigh = __neigh_lookup(&clip_tbl, &ip, rt->u.dst.dev, 1);
540 ip_rt_put(rt); 541 ip_rt_put(rt);
541 if (!neigh) 542 if (!neigh)
542 return -ENOMEM; 543 return -ENOMEM;
543 entry = NEIGH2ENTRY(neigh); 544 entry = NEIGH2ENTRY(neigh);
544 if (entry != clip_vcc->entry) { 545 if (entry != clip_vcc->entry) {
545 if (!clip_vcc->entry) DPRINTK( !! 546 if (!clip_vcc->entry)
>> 547 pr_debug("setentry: add\n");
546 else { 548 else {
547 DPRINTK("setentry: upd !! 549 pr_debug("setentry: update\n");
548 unlink_clip_vcc(clip_v 550 unlink_clip_vcc(clip_vcc);
549 } 551 }
550 link_vcc(clip_vcc,entry); !! 552 link_vcc(clip_vcc, entry);
551 } 553 }
552 error = neigh_update(neigh, llc_oui, N !! 554 error = neigh_update(neigh, llc_oui, NUD_PERMANENT,
553 NEIGH_UPDATE_F_OV !! 555 NEIGH_UPDATE_F_OVERRIDE | NEIGH_UPDATE_F_ADMIN);
554 neigh_release(neigh); 556 neigh_release(neigh);
555 return error; 557 return error;
556 } 558 }
557 559
558 <<
559 static void clip_setup(struct net_device *dev) 560 static void clip_setup(struct net_device *dev)
560 { 561 {
561 dev->hard_start_xmit = clip_start_xmit 562 dev->hard_start_xmit = clip_start_xmit;
562 /* sg_xmit ... */ 563 /* sg_xmit ... */
563 dev->get_stats = clip_get_stats; 564 dev->get_stats = clip_get_stats;
564 dev->type = ARPHRD_ATM; 565 dev->type = ARPHRD_ATM;
565 dev->hard_header_len = RFC1483LLC_LEN; 566 dev->hard_header_len = RFC1483LLC_LEN;
566 dev->mtu = RFC1626_MTU; 567 dev->mtu = RFC1626_MTU;
567 dev->tx_queue_len = 100; /* "normal" q !! 568 dev->tx_queue_len = 100; /* "normal" queue (packets) */
568 /* When using a "real" qdisc, the !! 569 /* When using a "real" qdisc, the qdisc determines the queue */
569 /* length. tx_queue_len is only us !! 570 /* length. tx_queue_len is only used for the default case, */
570 /* without any more elaborate queu !! 571 /* without any more elaborate queuing. 100 is a reasonable */
571 /* compromise between decent burst !! 572 /* compromise between decent burst-tolerance and protection */
572 /* against memory hogs. */ !! 573 /* against memory hogs. */
573 } 574 }
574 575
575 <<
576 static int clip_create(int number) 576 static int clip_create(int number)
577 { 577 {
578 struct net_device *dev; 578 struct net_device *dev;
579 struct clip_priv *clip_priv; 579 struct clip_priv *clip_priv;
580 int error; 580 int error;
581 581
582 if (number != -1) { 582 if (number != -1) {
583 for (dev = clip_devs; dev; dev 583 for (dev = clip_devs; dev; dev = PRIV(dev)->next)
584 if (PRIV(dev)->number !! 584 if (PRIV(dev)->number == number)
585 } !! 585 return -EEXIST;
586 else { !! 586 } else {
587 number = 0; 587 number = 0;
588 for (dev = clip_devs; dev; dev 588 for (dev = clip_devs; dev; dev = PRIV(dev)->next)
589 if (PRIV(dev)->number 589 if (PRIV(dev)->number >= number)
590 number = PRIV( !! 590 number = PRIV(dev)->number + 1;
591 } 591 }
592 dev = alloc_netdev(sizeof(struct clip_ 592 dev = alloc_netdev(sizeof(struct clip_priv), "", clip_setup);
593 if (!dev) 593 if (!dev)
594 return -ENOMEM; 594 return -ENOMEM;
595 clip_priv = PRIV(dev); 595 clip_priv = PRIV(dev);
596 sprintf(dev->name,"atm%d",number); !! 596 sprintf(dev->name, "atm%d", number);
597 spin_lock_init(&clip_priv->xoff_lock); 597 spin_lock_init(&clip_priv->xoff_lock);
598 clip_priv->number = number; 598 clip_priv->number = number;
599 error = register_netdev(dev); 599 error = register_netdev(dev);
600 if (error) { 600 if (error) {
601 free_netdev(dev); 601 free_netdev(dev);
602 return error; 602 return error;
603 } 603 }
604 clip_priv->next = clip_devs; 604 clip_priv->next = clip_devs;
605 clip_devs = dev; 605 clip_devs = dev;
606 DPRINTK("registered (net:%s)\n",dev->n !! 606 pr_debug("registered (net:%s)\n", dev->name);
607 return number; 607 return number;
608 } 608 }
609 609
610 !! 610 static int clip_device_event(struct notifier_block *this, unsigned long event,
611 static int clip_device_event(struct notifier_b !! 611 void *arg)
612 void *dev) <<
613 { 612 {
>> 613 struct net_device *dev = arg;
>> 614
>> 615 if (dev->nd_net != &init_net)
>> 616 return NOTIFY_DONE;
>> 617
>> 618 if (event == NETDEV_UNREGISTER) {
>> 619 neigh_ifdown(&clip_tbl, dev);
>> 620 return NOTIFY_DONE;
>> 621 }
>> 622
614 /* ignore non-CLIP devices */ 623 /* ignore non-CLIP devices */
615 if (((struct net_device *) dev)->type !! 624 if (dev->type != ARPHRD_ATM || dev->hard_start_xmit != clip_start_xmit)
616 ((struct net_device *) dev)->hard_ <<
617 return NOTIFY_DONE; 625 return NOTIFY_DONE;
>> 626
618 switch (event) { 627 switch (event) {
619 case NETDEV_UP: !! 628 case NETDEV_UP:
620 DPRINTK("clip_device_e !! 629 pr_debug("clip_device_event NETDEV_UP\n");
621 (void) to_atmarpd(act_ !! 630 to_atmarpd(act_up, PRIV(dev)->number, 0);
622 break; !! 631 break;
623 case NETDEV_GOING_DOWN: !! 632 case NETDEV_GOING_DOWN:
624 DPRINTK("clip_device_e !! 633 pr_debug("clip_device_event NETDEV_DOWN\n");
625 (void) to_atmarpd(act_ !! 634 to_atmarpd(act_down, PRIV(dev)->number, 0);
626 break; !! 635 break;
627 case NETDEV_CHANGE: !! 636 case NETDEV_CHANGE:
628 case NETDEV_CHANGEMTU: !! 637 case NETDEV_CHANGEMTU:
629 DPRINTK("clip_device_e !! 638 pr_debug("clip_device_event NETDEV_CHANGE*\n");
630 (void) to_atmarpd(act_ !! 639 to_atmarpd(act_change, PRIV(dev)->number, 0);
631 break; !! 640 break;
632 case NETDEV_REBOOT: <<
633 case NETDEV_REGISTER: <<
634 case NETDEV_DOWN: <<
635 DPRINTK("clip_device_e <<
636 /* ignore */ <<
637 break; <<
638 default: <<
639 printk(KERN_WARNING "c <<
640 "%ld\n",event); <<
641 break; <<
642 } 641 }
643 return NOTIFY_DONE; 642 return NOTIFY_DONE;
644 } 643 }
645 644
646 !! 645 static int clip_inet_event(struct notifier_block *this, unsigned long event,
647 static int clip_inet_event(struct notifier_blo !! 646 void *ifa)
648 void *ifa) <<
649 { 647 {
650 struct in_device *in_dev; 648 struct in_device *in_dev;
651 649
652 in_dev = ((struct in_ifaddr *) ifa)->i !! 650 in_dev = ((struct in_ifaddr *)ifa)->ifa_dev;
653 if (!in_dev || !in_dev->dev) { 651 if (!in_dev || !in_dev->dev) {
654 printk(KERN_WARNING "clip_inet 652 printk(KERN_WARNING "clip_inet_event: no device\n");
655 return NOTIFY_DONE; 653 return NOTIFY_DONE;
656 } 654 }
657 /* 655 /*
658 * Transitions are of the down-change- 656 * Transitions are of the down-change-up type, so it's sufficient to
659 * handle the change on up. 657 * handle the change on up.
660 */ 658 */
661 if (event != NETDEV_UP) return NOTIFY_ !! 659 if (event != NETDEV_UP)
662 return clip_device_event(this,NETDEV_C !! 660 return NOTIFY_DONE;
>> 661 return clip_device_event(this, NETDEV_CHANGE, in_dev->dev);
663 } 662 }
664 663
665 664
666 static struct notifier_block clip_dev_notifier 665 static struct notifier_block clip_dev_notifier = {
667 clip_device_event, !! 666 .notifier_call = clip_device_event,
668 NULL, <<
669 0 <<
670 }; 667 };
671 668
672 669
673 670
674 static struct notifier_block clip_inet_notifie 671 static struct notifier_block clip_inet_notifier = {
675 clip_inet_event, !! 672 .notifier_call = clip_inet_event,
676 NULL, <<
677 0 <<
678 }; 673 };
679 674
680 675
681 676
682 static void atmarpd_close(struct atm_vcc *vcc) 677 static void atmarpd_close(struct atm_vcc *vcc)
683 { 678 {
684 DPRINTK("atmarpd_close\n"); !! 679 pr_debug("atmarpd_close\n");
685 atmarpd = NULL; /* assumed to be atomi !! 680
686 barrier(); !! 681 rtnl_lock();
687 unregister_inetaddr_notifier(&clip_ine !! 682 atmarpd = NULL;
688 unregister_netdevice_notifier(&clip_de !! 683 skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
689 if (skb_peek(&vcc->sk->sk_receive_queu !! 684 rtnl_unlock();
690 printk(KERN_ERR "atmarpd_close !! 685
691 "pending\n"); !! 686 pr_debug("(done)\n");
692 skb_queue_purge(&vcc->sk->sk_receive_q <<
693 DPRINTK("(done)\n"); <<
694 module_put(THIS_MODULE); 687 module_put(THIS_MODULE);
695 } 688 }
696 689
697 690
698 static struct atmdev_ops atmarpd_dev_ops = { 691 static struct atmdev_ops atmarpd_dev_ops = {
699 .close = atmarpd_close 692 .close = atmarpd_close
700 }; 693 };
701 694
702 695
703 static struct atm_dev atmarpd_dev = { 696 static struct atm_dev atmarpd_dev = {
704 .ops = &atmarpd_dev_o 697 .ops = &atmarpd_dev_ops,
705 .type = "arpd", 698 .type = "arpd",
706 .number = 999, 699 .number = 999,
707 .lock = SPIN_LOCK_UNLO !! 700 .lock = __SPIN_LOCK_UNLOCKED(atmarpd_dev.lock)
708 }; 701 };
709 702
710 703
711 static int atm_init_atmarp(struct atm_vcc *vcc 704 static int atm_init_atmarp(struct atm_vcc *vcc)
712 { 705 {
713 if (atmarpd) return -EADDRINUSE; !! 706 rtnl_lock();
714 if (start_timer) { !! 707 if (atmarpd) {
715 start_timer = 0; !! 708 rtnl_unlock();
716 init_timer(&idle_timer); !! 709 return -EADDRINUSE;
717 idle_timer.expires = jiffies+C <<
718 idle_timer.function = idle_tim <<
719 add_timer(&idle_timer); <<
720 } 710 }
>> 711
>> 712 mod_timer(&idle_timer, jiffies+CLIP_CHECK_INTERVAL*HZ);
>> 713
721 atmarpd = vcc; 714 atmarpd = vcc;
722 set_bit(ATM_VF_META,&vcc->flags); 715 set_bit(ATM_VF_META,&vcc->flags);
723 set_bit(ATM_VF_READY,&vcc->flags); 716 set_bit(ATM_VF_READY,&vcc->flags);
724 /* allow replies and avoid getting 717 /* allow replies and avoid getting closed if signaling dies */
725 vcc->dev = &atmarpd_dev; 718 vcc->dev = &atmarpd_dev;
726 vcc_insert_socket(vcc->sk); !! 719 vcc_insert_socket(sk_atm(vcc));
727 vcc->push = NULL; 720 vcc->push = NULL;
728 vcc->pop = NULL; /* crash */ 721 vcc->pop = NULL; /* crash */
729 vcc->push_oam = NULL; /* crash */ 722 vcc->push_oam = NULL; /* crash */
730 if (register_netdevice_notifier(&clip_ !! 723 rtnl_unlock();
731 printk(KERN_ERR "register_netd <<
732 if (register_inetaddr_notifier(&clip_i <<
733 printk(KERN_ERR "register_inet <<
734 return 0; 724 return 0;
735 } 725 }
736 726
737 static int clip_ioctl(struct socket *sock, uns 727 static int clip_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
738 { 728 {
739 struct atm_vcc *vcc = ATM_SD(sock); 729 struct atm_vcc *vcc = ATM_SD(sock);
740 int err = 0; 730 int err = 0;
741 731
742 switch (cmd) { 732 switch (cmd) {
743 case SIOCMKCLIP: !! 733 case SIOCMKCLIP:
744 case ATMARPD_CTRL: !! 734 case ATMARPD_CTRL:
745 case ATMARP_MKIP: !! 735 case ATMARP_MKIP:
746 case ATMARP_SETENTRY: !! 736 case ATMARP_SETENTRY:
747 case ATMARP_ENCAP: !! 737 case ATMARP_ENCAP:
748 if (!capable(CAP_NET_A !! 738 if (!capable(CAP_NET_ADMIN))
749 return -EPERM; !! 739 return -EPERM;
750 break; !! 740 break;
751 default: !! 741 default:
752 return -ENOIOCTLCMD; !! 742 return -ENOIOCTLCMD;
753 } 743 }
754 744
755 switch (cmd) { 745 switch (cmd) {
756 case SIOCMKCLIP: !! 746 case SIOCMKCLIP:
757 err = clip_create(arg) !! 747 err = clip_create(arg);
758 break; !! 748 break;
759 case ATMARPD_CTRL: !! 749 case ATMARPD_CTRL:
760 err = atm_init_atmarp( !! 750 err = atm_init_atmarp(vcc);
761 if (!err) { !! 751 if (!err) {
762 sock->state = !! 752 sock->state = SS_CONNECTED;
763 __module_get(T !! 753 __module_get(THIS_MODULE);
764 } !! 754 }
765 break; !! 755 break;
766 case ATMARP_MKIP: !! 756 case ATMARP_MKIP:
767 err = clip_mkip(vcc ,a !! 757 err = clip_mkip(vcc, arg);
768 break; !! 758 break;
769 case ATMARP_SETENTRY: !! 759 case ATMARP_SETENTRY:
770 err = clip_setentry(vc !! 760 err = clip_setentry(vcc, (__force __be32)arg);
771 break; !! 761 break;
772 case ATMARP_ENCAP: !! 762 case ATMARP_ENCAP:
773 err = clip_encap(vcc, !! 763 err = clip_encap(vcc, arg);
774 break; !! 764 break;
775 } 765 }
776 return err; 766 return err;
777 } 767 }
778 768
779 static struct atm_ioctl clip_ioctl_ops = { 769 static struct atm_ioctl clip_ioctl_ops = {
780 .owner = THIS_MODULE, !! 770 .owner = THIS_MODULE,
781 .ioctl = clip_ioctl, !! 771 .ioctl = clip_ioctl,
782 }; 772 };
783 773
784 #ifdef CONFIG_PROC_FS 774 #ifdef CONFIG_PROC_FS
785 775
786 static void svc_addr(struct seq_file *seq, str 776 static void svc_addr(struct seq_file *seq, struct sockaddr_atmsvc *addr)
787 { 777 {
788 static int code[] = { 1,2,10,6,1,0 }; !! 778 static int code[] = { 1, 2, 10, 6, 1, 0 };
789 static int e164[] = { 1,8,4,6,1,0 }; !! 779 static int e164[] = { 1, 8, 4, 6, 1, 0 };
790 780
791 if (*addr->sas_addr.pub) { 781 if (*addr->sas_addr.pub) {
792 seq_printf(seq, "%s", addr->sa 782 seq_printf(seq, "%s", addr->sas_addr.pub);
793 if (*addr->sas_addr.prv) 783 if (*addr->sas_addr.prv)
794 seq_putc(seq, '+'); 784 seq_putc(seq, '+');
795 } else if (!*addr->sas_addr.prv) { 785 } else if (!*addr->sas_addr.prv) {
796 seq_printf(seq, "%s", "(none)" 786 seq_printf(seq, "%s", "(none)");
797 return; 787 return;
798 } 788 }
799 if (*addr->sas_addr.prv) { 789 if (*addr->sas_addr.prv) {
800 unsigned char *prv = addr->sas 790 unsigned char *prv = addr->sas_addr.prv;
801 int *fields; 791 int *fields;
802 int i, j; 792 int i, j;
803 793
804 fields = *prv == ATM_AFI_E164 794 fields = *prv == ATM_AFI_E164 ? e164 : code;
805 for (i = 0; fields[i]; i++) { 795 for (i = 0; fields[i]; i++) {
806 for (j = fields[i]; j; 796 for (j = fields[i]; j; j--)
807 seq_printf(seq 797 seq_printf(seq, "%02X", *prv++);
808 if (fields[i+1]) !! 798 if (fields[i + 1])
809 seq_putc(seq, 799 seq_putc(seq, '.');
810 } 800 }
811 } 801 }
812 } 802 }
813 803
814 /* This means the neighbour entry has no attac 804 /* This means the neighbour entry has no attached VCC objects. */
815 #define SEQ_NO_VCC_TOKEN ((void *) 2) 805 #define SEQ_NO_VCC_TOKEN ((void *) 2)
816 806
817 static void atmarp_info(struct seq_file *seq, 807 static void atmarp_info(struct seq_file *seq, struct net_device *dev,
818 struct atmarp_entry *e 808 struct atmarp_entry *entry, struct clip_vcc *clip_vcc)
819 { 809 {
820 unsigned long exp; 810 unsigned long exp;
821 char buf[17]; 811 char buf[17];
822 int svc, llc, off; 812 int svc, llc, off;
823 813
824 svc = ((clip_vcc == SEQ_NO_VCC_TOKEN) 814 svc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
825 (clip_vcc->vcc->sk->sk_family = !! 815 (sk_atm(clip_vcc->vcc)->sk_family == AF_ATMSVC));
826 816
827 llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) !! 817 llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) || clip_vcc->encap);
828 clip_vcc->encap); <<
829 818
830 if (clip_vcc == SEQ_NO_VCC_TOKEN) 819 if (clip_vcc == SEQ_NO_VCC_TOKEN)
831 exp = entry->neigh->used; 820 exp = entry->neigh->used;
832 else 821 else
833 exp = clip_vcc->last_use; 822 exp = clip_vcc->last_use;
834 823
835 exp = (jiffies - exp) / HZ; 824 exp = (jiffies - exp) / HZ;
836 825
837 seq_printf(seq, "%-6s%-4s%-4s%5ld ", 826 seq_printf(seq, "%-6s%-4s%-4s%5ld ",
838 dev->name, !! 827 dev->name, svc ? "SVC" : "PVC", llc ? "LLC" : "NULL", exp);
839 svc ? "SVC" : "PVC", <<
840 llc ? "LLC" : "NULL", <<
841 exp); <<
842 828
843 off = scnprintf(buf, sizeof(buf) - 1, 829 off = scnprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d",
844 NIPQUAD(entry->ip)); 830 NIPQUAD(entry->ip));
845 while (off < 16) 831 while (off < 16)
846 buf[off++] = ' '; 832 buf[off++] = ' ';
847 buf[off] = '\0'; 833 buf[off] = '\0';
848 seq_printf(seq, "%s", buf); 834 seq_printf(seq, "%s", buf);
849 835
850 if (clip_vcc == SEQ_NO_VCC_TOKEN) { 836 if (clip_vcc == SEQ_NO_VCC_TOKEN) {
851 if (time_before(jiffies, entry 837 if (time_before(jiffies, entry->expires))
852 seq_printf(seq, "(reso 838 seq_printf(seq, "(resolving)\n");
853 else 839 else
854 seq_printf(seq, "(expi 840 seq_printf(seq, "(expired, ref %d)\n",
855 atomic_read 841 atomic_read(&entry->neigh->refcnt));
856 } else if (!svc) { 842 } else if (!svc) {
857 seq_printf(seq, "%d.%d.%d\n", 843 seq_printf(seq, "%d.%d.%d\n",
858 clip_vcc->vcc->dev- 844 clip_vcc->vcc->dev->number,
859 clip_vcc->vcc->vpi, !! 845 clip_vcc->vcc->vpi, clip_vcc->vcc->vci);
860 clip_vcc->vcc->vci) <<
861 } else { 846 } else {
862 svc_addr(seq, &clip_vcc->vcc-> 847 svc_addr(seq, &clip_vcc->vcc->remote);
863 seq_putc(seq, '\n'); 848 seq_putc(seq, '\n');
864 } 849 }
865 } 850 }
866 851
867 struct clip_seq_state { 852 struct clip_seq_state {
868 /* This member must be first. */ 853 /* This member must be first. */
869 struct neigh_seq_state ns; 854 struct neigh_seq_state ns;
870 855
871 /* Local to clip specific iteration. * 856 /* Local to clip specific iteration. */
872 struct clip_vcc *vcc; 857 struct clip_vcc *vcc;
873 }; 858 };
874 859
875 static struct clip_vcc *clip_seq_next_vcc(stru 860 static struct clip_vcc *clip_seq_next_vcc(struct atmarp_entry *e,
876 stru 861 struct clip_vcc *curr)
877 { 862 {
878 if (!curr) { 863 if (!curr) {
879 curr = e->vccs; 864 curr = e->vccs;
880 if (!curr) 865 if (!curr)
881 return SEQ_NO_VCC_TOKE 866 return SEQ_NO_VCC_TOKEN;
882 return curr; 867 return curr;
883 } 868 }
884 if (curr == SEQ_NO_VCC_TOKEN) 869 if (curr == SEQ_NO_VCC_TOKEN)
885 return NULL; 870 return NULL;
886 871
887 curr = curr->next; 872 curr = curr->next;
888 873
889 return curr; 874 return curr;
890 } 875 }
891 876
892 static void *clip_seq_vcc_walk(struct clip_seq 877 static void *clip_seq_vcc_walk(struct clip_seq_state *state,
893 struct atmarp_e !! 878 struct atmarp_entry *e, loff_t * pos)
894 { 879 {
895 struct clip_vcc *vcc = state->vcc; 880 struct clip_vcc *vcc = state->vcc;
896 881
897 vcc = clip_seq_next_vcc(e, vcc); 882 vcc = clip_seq_next_vcc(e, vcc);
898 if (vcc && pos != NULL) { 883 if (vcc && pos != NULL) {
899 while (*pos) { 884 while (*pos) {
900 vcc = clip_seq_next_vc 885 vcc = clip_seq_next_vcc(e, vcc);
901 if (!vcc) 886 if (!vcc)
902 break; 887 break;
903 --(*pos); 888 --(*pos);
904 } 889 }
905 } 890 }
906 state->vcc = vcc; 891 state->vcc = vcc;
907 892
908 return vcc; 893 return vcc;
909 } 894 }
910 !! 895
911 static void *clip_seq_sub_iter(struct neigh_se 896 static void *clip_seq_sub_iter(struct neigh_seq_state *_state,
912 struct neighbou !! 897 struct neighbour *n, loff_t * pos)
913 { 898 {
914 struct clip_seq_state *state = (struct !! 899 struct clip_seq_state *state = (struct clip_seq_state *)_state;
915 900
916 return clip_seq_vcc_walk(state, NEIGH2 901 return clip_seq_vcc_walk(state, NEIGH2ENTRY(n), pos);
917 } 902 }
918 903
919 static void *clip_seq_start(struct seq_file *s !! 904 static void *clip_seq_start(struct seq_file *seq, loff_t * pos)
920 { 905 {
>> 906 struct clip_seq_state *state = seq->private;
>> 907 state->ns.neigh_sub_iter = clip_seq_sub_iter;
921 return neigh_seq_start(seq, pos, &clip 908 return neigh_seq_start(seq, pos, &clip_tbl, NEIGH_SEQ_NEIGH_ONLY);
922 } 909 }
923 910
924 static int clip_seq_show(struct seq_file *seq, 911 static int clip_seq_show(struct seq_file *seq, void *v)
925 { 912 {
926 static char atm_arp_banner[] = !! 913 static char atm_arp_banner[] =
927 "IPitf TypeEncp Idle IP addres !! 914 "IPitf TypeEncp Idle IP address ATM address\n";
928 915
929 if (v == SEQ_START_TOKEN) { 916 if (v == SEQ_START_TOKEN) {
930 seq_puts(seq, atm_arp_banner); 917 seq_puts(seq, atm_arp_banner);
931 } else { 918 } else {
932 struct clip_seq_state *state = 919 struct clip_seq_state *state = seq->private;
933 struct neighbour *n = v; 920 struct neighbour *n = v;
934 struct clip_vcc *vcc = state-> 921 struct clip_vcc *vcc = state->vcc;
935 922
936 atmarp_info(seq, n->dev, NEIGH 923 atmarp_info(seq, n->dev, NEIGH2ENTRY(n), vcc);
937 } 924 }
938 return 0; !! 925 return 0;
939 } 926 }
940 927
941 static struct seq_operations arp_seq_ops = { !! 928 static const struct seq_operations arp_seq_ops = {
942 .start = clip_seq_start, 929 .start = clip_seq_start,
943 .next = neigh_seq_next, 930 .next = neigh_seq_next,
944 .stop = neigh_seq_stop, 931 .stop = neigh_seq_stop,
945 .show = clip_seq_show, 932 .show = clip_seq_show,
946 }; 933 };
947 934
948 static int arp_seq_open(struct inode *inode, s 935 static int arp_seq_open(struct inode *inode, struct file *file)
949 { 936 {
950 struct clip_seq_state *state; !! 937 return seq_open_net(inode, file, &arp_seq_ops,
951 struct seq_file *seq; !! 938 sizeof(struct clip_seq_state));
952 int rc = -EAGAIN; <<
953 <<
954 state = kmalloc(sizeof(*state), GFP_KE <<
955 if (!state) { <<
956 rc = -ENOMEM; <<
957 goto out_kfree; <<
958 } <<
959 memset(state, 0, sizeof(*state)); <<
960 state->ns.neigh_sub_iter = clip_seq_su <<
961 <<
962 rc = seq_open(file, &arp_seq_ops); <<
963 if (rc) <<
964 goto out_kfree; <<
965 <<
966 seq = file->private_data; <<
967 seq->private = state; <<
968 out: <<
969 return rc; <<
970 <<
971 out_kfree: <<
972 kfree(state); <<
973 goto out; <<
974 } 939 }
975 940
976 static struct file_operations arp_seq_fops = { !! 941 static const struct file_operations arp_seq_fops = {
977 .open = arp_seq_open, 942 .open = arp_seq_open,
978 .read = seq_read, 943 .read = seq_read,
979 .llseek = seq_lseek, 944 .llseek = seq_lseek,
980 .release = seq_release_private, !! 945 .release = seq_release_net,
981 .owner = THIS_MODULE 946 .owner = THIS_MODULE
982 }; 947 };
983 #endif 948 #endif
984 949
>> 950 static void atm_clip_exit_noproc(void);
>> 951
985 static int __init atm_clip_init(void) 952 static int __init atm_clip_init(void)
986 { 953 {
987 neigh_table_init(&clip_tbl); !! 954 neigh_table_init_no_netlink(&clip_tbl);
988 955
989 clip_tbl_hook = &clip_tbl; 956 clip_tbl_hook = &clip_tbl;
990 register_atm_ioctl(&clip_ioctl_ops); 957 register_atm_ioctl(&clip_ioctl_ops);
>> 958 register_netdevice_notifier(&clip_dev_notifier);
>> 959 register_inetaddr_notifier(&clip_inet_notifier);
>> 960
>> 961 setup_timer(&idle_timer, idle_timer_check, 0);
991 962
992 #ifdef CONFIG_PROC_FS 963 #ifdef CONFIG_PROC_FS
993 { !! 964 {
994 struct proc_dir_entry *p; !! 965 struct proc_dir_entry *p;
995 966
996 p = create_proc_entry("arp", S_IRUGO, !! 967 p = proc_create("arp", S_IRUGO, atm_proc_root, &arp_seq_fops);
997 if (p) !! 968 if (!p) {
998 p->proc_fops = &arp_seq_fops; !! 969 printk(KERN_ERR "Unable to initialize "
999 } !! 970 "/proc/net/atm/arp\n");
>> 971 atm_clip_exit_noproc();
>> 972 return -ENOMEM;
>> 973 }
>> 974 }
1000 #endif 975 #endif
1001 976
1002 return 0; 977 return 0;
1003 } 978 }
1004 979
1005 static void __exit atm_clip_exit(void) !! 980 static void atm_clip_exit_noproc(void)
1006 { 981 {
1007 struct net_device *dev, *next; 982 struct net_device *dev, *next;
1008 983
1009 remove_proc_entry("arp", atm_proc_roo !! 984 unregister_inetaddr_notifier(&clip_inet_notifier);
>> 985 unregister_netdevice_notifier(&clip_dev_notifier);
1010 986
1011 deregister_atm_ioctl(&clip_ioctl_ops) 987 deregister_atm_ioctl(&clip_ioctl_ops);
1012 988
1013 /* First, stop the idle timer, so it 989 /* First, stop the idle timer, so it stops banging
1014 * on the table. 990 * on the table.
1015 */ 991 */
1016 if (start_timer == 0) !! 992 del_timer_sync(&idle_timer);
1017 del_timer(&idle_timer); <<
1018 993
1019 /* Next, purge the table, so that the 994 /* Next, purge the table, so that the device
1020 * unregister loop below does not han 995 * unregister loop below does not hang due to
1021 * device references remaining in the 996 * device references remaining in the table.
1022 */ 997 */
1023 neigh_ifdown(&clip_tbl, NULL); 998 neigh_ifdown(&clip_tbl, NULL);
1024 999
1025 dev = clip_devs; 1000 dev = clip_devs;
1026 while (dev) { 1001 while (dev) {
1027 next = PRIV(dev)->next; 1002 next = PRIV(dev)->next;
1028 unregister_netdev(dev); 1003 unregister_netdev(dev);
1029 free_netdev(dev); 1004 free_netdev(dev);
1030 dev = next; 1005 dev = next;
1031 } 1006 }
1032 1007
1033 /* Now it is safe to fully shutdown w 1008 /* Now it is safe to fully shutdown whole table. */
1034 neigh_table_clear(&clip_tbl); 1009 neigh_table_clear(&clip_tbl);
1035 1010
1036 clip_tbl_hook = NULL; 1011 clip_tbl_hook = NULL;
1037 } 1012 }
1038 1013
>> 1014 static void __exit atm_clip_exit(void)
>> 1015 {
>> 1016 remove_proc_entry("arp", atm_proc_root);
>> 1017
>> 1018 atm_clip_exit_noproc();
>> 1019 }
>> 1020
1039 module_init(atm_clip_init); 1021 module_init(atm_clip_init);
1040 module_exit(atm_clip_exit); 1022 module_exit(atm_clip_exit);
1041 !! 1023 MODULE_AUTHOR("Werner Almesberger");
>> 1024 MODULE_DESCRIPTION("Classical/IP over ATM interface");
1042 MODULE_LICENSE("GPL"); 1025 MODULE_LICENSE("GPL");
1043 1026
|
This page was automatically generated by the
LXR engine.
|