~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/netrom/nr_route.c

Version: ~ [ linux-5.11 ] ~ [ linux-5.10.17 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.99 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.176 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.221 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.257 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.257 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * This program is free software; you can redistribute it and/or modify
  3  * it under the terms of the GNU General Public License as published by
  4  * the Free Software Foundation; either version 2 of the License, or
  5  * (at your option) any later version.
  6  *
  7  * Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
  8  * Copyright Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
  9  * Copyright Tomi Manninen OH2BNS (oh2bns@sral.fi)
 10  */
 11 #include <linux/errno.h>
 12 #include <linux/types.h>
 13 #include <linux/socket.h>
 14 #include <linux/in.h>
 15 #include <linux/kernel.h>
 16 #include <linux/timer.h>
 17 #include <linux/string.h>
 18 #include <linux/sockios.h>
 19 #include <linux/net.h>
 20 #include <linux/slab.h>
 21 #include <net/ax25.h>
 22 #include <linux/inet.h>
 23 #include <linux/netdevice.h>
 24 #include <net/arp.h>
 25 #include <linux/if_arp.h>
 26 #include <linux/skbuff.h>
 27 #include <net/sock.h>
 28 #include <linux/uaccess.h>
 29 #include <linux/fcntl.h>
 30 #include <linux/termios.h>      /* For TIOCINQ/OUTQ */
 31 #include <linux/mm.h>
 32 #include <linux/interrupt.h>
 33 #include <linux/notifier.h>
 34 #include <linux/init.h>
 35 #include <linux/spinlock.h>
 36 #include <net/netrom.h>
 37 #include <linux/seq_file.h>
 38 #include <linux/export.h>
 39 
 40 static unsigned int nr_neigh_no = 1;
 41 
 42 static HLIST_HEAD(nr_node_list);
 43 static DEFINE_SPINLOCK(nr_node_list_lock);
 44 static HLIST_HEAD(nr_neigh_list);
 45 static DEFINE_SPINLOCK(nr_neigh_list_lock);
 46 
 47 static struct nr_node *nr_node_get(ax25_address *callsign)
 48 {
 49         struct nr_node *found = NULL;
 50         struct nr_node *nr_node;
 51 
 52         spin_lock_bh(&nr_node_list_lock);
 53         nr_node_for_each(nr_node, &nr_node_list)
 54                 if (ax25cmp(callsign, &nr_node->callsign) == 0) {
 55                         nr_node_hold(nr_node);
 56                         found = nr_node;
 57                         break;
 58                 }
 59         spin_unlock_bh(&nr_node_list_lock);
 60         return found;
 61 }
 62 
 63 static struct nr_neigh *nr_neigh_get_dev(ax25_address *callsign,
 64                                          struct net_device *dev)
 65 {
 66         struct nr_neigh *found = NULL;
 67         struct nr_neigh *nr_neigh;
 68 
 69         spin_lock_bh(&nr_neigh_list_lock);
 70         nr_neigh_for_each(nr_neigh, &nr_neigh_list)
 71                 if (ax25cmp(callsign, &nr_neigh->callsign) == 0 &&
 72                     nr_neigh->dev == dev) {
 73                         nr_neigh_hold(nr_neigh);
 74                         found = nr_neigh;
 75                         break;
 76                 }
 77         spin_unlock_bh(&nr_neigh_list_lock);
 78         return found;
 79 }
 80 
 81 static void nr_remove_neigh(struct nr_neigh *);
 82 
 83 /*      re-sort the routes in quality order.    */
 84 static void re_sort_routes(struct nr_node *nr_node, int x, int y)
 85 {
 86         if (nr_node->routes[y].quality > nr_node->routes[x].quality) {
 87                 if (nr_node->which == x)
 88                         nr_node->which = y;
 89                 else if (nr_node->which == y)
 90                         nr_node->which = x;
 91 
 92                 swap(nr_node->routes[x], nr_node->routes[y]);
 93         }
 94 }
 95 
 96 /*
 97  *      Add a new route to a node, and in the process add the node and the
 98  *      neighbour if it is new.
 99  */
100 static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
101         ax25_address *ax25, ax25_digi *ax25_digi, struct net_device *dev,
102         int quality, int obs_count)
103 {
104         struct nr_node  *nr_node;
105         struct nr_neigh *nr_neigh;
106         int i, found;
107         struct net_device *odev;
108 
109         if ((odev=nr_dev_get(nr)) != NULL) {    /* Can't add routes to ourself */
110                 dev_put(odev);
111                 return -EINVAL;
112         }
113 
114         nr_node = nr_node_get(nr);
115 
116         nr_neigh = nr_neigh_get_dev(ax25, dev);
117 
118         /*
119          * The L2 link to a neighbour has failed in the past
120          * and now a frame comes from this neighbour. We assume
121          * it was a temporary trouble with the link and reset the
122          * routes now (and not wait for a node broadcast).
123          */
124         if (nr_neigh != NULL && nr_neigh->failed != 0 && quality == 0) {
125                 struct nr_node *nr_nodet;
126 
127                 spin_lock_bh(&nr_node_list_lock);
128                 nr_node_for_each(nr_nodet, &nr_node_list) {
129                         nr_node_lock(nr_nodet);
130                         for (i = 0; i < nr_nodet->count; i++)
131                                 if (nr_nodet->routes[i].neighbour == nr_neigh)
132                                         if (i < nr_nodet->which)
133                                                 nr_nodet->which = i;
134                         nr_node_unlock(nr_nodet);
135                 }
136                 spin_unlock_bh(&nr_node_list_lock);
137         }
138 
139         if (nr_neigh != NULL)
140                 nr_neigh->failed = 0;
141 
142         if (quality == 0 && nr_neigh != NULL && nr_node != NULL) {
143                 nr_neigh_put(nr_neigh);
144                 nr_node_put(nr_node);
145                 return 0;
146         }
147 
148         if (nr_neigh == NULL) {
149                 if ((nr_neigh = kmalloc(sizeof(*nr_neigh), GFP_ATOMIC)) == NULL) {
150                         if (nr_node)
151                                 nr_node_put(nr_node);
152                         return -ENOMEM;
153                 }
154 
155                 nr_neigh->callsign = *ax25;
156                 nr_neigh->digipeat = NULL;
157                 nr_neigh->ax25     = NULL;
158                 nr_neigh->dev      = dev;
159                 nr_neigh->quality  = sysctl_netrom_default_path_quality;
160                 nr_neigh->locked   = 0;
161                 nr_neigh->count    = 0;
162                 nr_neigh->number   = nr_neigh_no++;
163                 nr_neigh->failed   = 0;
164                 refcount_set(&nr_neigh->refcount, 1);
165 
166                 if (ax25_digi != NULL && ax25_digi->ndigi > 0) {
167                         nr_neigh->digipeat = kmemdup(ax25_digi,
168                                                      sizeof(*ax25_digi),
169                                                      GFP_KERNEL);
170                         if (nr_neigh->digipeat == NULL) {
171                                 kfree(nr_neigh);
172                                 if (nr_node)
173                                         nr_node_put(nr_node);
174                                 return -ENOMEM;
175                         }
176                 }
177 
178                 spin_lock_bh(&nr_neigh_list_lock);
179                 hlist_add_head(&nr_neigh->neigh_node, &nr_neigh_list);
180                 nr_neigh_hold(nr_neigh);
181                 spin_unlock_bh(&nr_neigh_list_lock);
182         }
183 
184         if (quality != 0 && ax25cmp(nr, ax25) == 0 && !nr_neigh->locked)
185                 nr_neigh->quality = quality;
186 
187         if (nr_node == NULL) {
188                 if ((nr_node = kmalloc(sizeof(*nr_node), GFP_ATOMIC)) == NULL) {
189                         if (nr_neigh)
190                                 nr_neigh_put(nr_neigh);
191                         return -ENOMEM;
192                 }
193 
194                 nr_node->callsign = *nr;
195                 strcpy(nr_node->mnemonic, mnemonic);
196 
197                 nr_node->which = 0;
198                 nr_node->count = 1;
199                 refcount_set(&nr_node->refcount, 1);
200                 spin_lock_init(&nr_node->node_lock);
201 
202                 nr_node->routes[0].quality   = quality;
203                 nr_node->routes[0].obs_count = obs_count;
204                 nr_node->routes[0].neighbour = nr_neigh;
205 
206                 nr_neigh_hold(nr_neigh);
207                 nr_neigh->count++;
208 
209                 spin_lock_bh(&nr_node_list_lock);
210                 hlist_add_head(&nr_node->node_node, &nr_node_list);
211                 /* refcount initialized at 1 */
212                 spin_unlock_bh(&nr_node_list_lock);
213 
214                 return 0;
215         }
216         nr_node_lock(nr_node);
217 
218         if (quality != 0)
219                 strcpy(nr_node->mnemonic, mnemonic);
220 
221         for (found = 0, i = 0; i < nr_node->count; i++) {
222                 if (nr_node->routes[i].neighbour == nr_neigh) {
223                         nr_node->routes[i].quality   = quality;
224                         nr_node->routes[i].obs_count = obs_count;
225                         found = 1;
226                         break;
227                 }
228         }
229 
230         if (!found) {
231                 /* We have space at the bottom, slot it in */
232                 if (nr_node->count < 3) {
233                         nr_node->routes[2] = nr_node->routes[1];
234                         nr_node->routes[1] = nr_node->routes[0];
235 
236                         nr_node->routes[0].quality   = quality;
237                         nr_node->routes[0].obs_count = obs_count;
238                         nr_node->routes[0].neighbour = nr_neigh;
239 
240                         nr_node->which++;
241                         nr_node->count++;
242                         nr_neigh_hold(nr_neigh);
243                         nr_neigh->count++;
244                 } else {
245                         /* It must be better than the worst */
246                         if (quality > nr_node->routes[2].quality) {
247                                 nr_node->routes[2].neighbour->count--;
248                                 nr_neigh_put(nr_node->routes[2].neighbour);
249 
250                                 if (nr_node->routes[2].neighbour->count == 0 && !nr_node->routes[2].neighbour->locked)
251                                         nr_remove_neigh(nr_node->routes[2].neighbour);
252 
253                                 nr_node->routes[2].quality   = quality;
254                                 nr_node->routes[2].obs_count = obs_count;
255                                 nr_node->routes[2].neighbour = nr_neigh;
256 
257                                 nr_neigh_hold(nr_neigh);
258                                 nr_neigh->count++;
259                         }
260                 }
261         }
262 
263         /* Now re-sort the routes in quality order */
264         switch (nr_node->count) {
265         case 3:
266                 re_sort_routes(nr_node, 0, 1);
267                 re_sort_routes(nr_node, 1, 2);
268                 /* fall through */
269         case 2:
270                 re_sort_routes(nr_node, 0, 1);
271         case 1:
272                 break;
273         }
274 
275         for (i = 0; i < nr_node->count; i++) {
276                 if (nr_node->routes[i].neighbour == nr_neigh) {
277                         if (i < nr_node->which)
278                                 nr_node->which = i;
279                         break;
280                 }
281         }
282 
283         nr_neigh_put(nr_neigh);
284         nr_node_unlock(nr_node);
285         nr_node_put(nr_node);
286         return 0;
287 }
288 
289 static inline void __nr_remove_node(struct nr_node *nr_node)
290 {
291         hlist_del_init(&nr_node->node_node);
292         nr_node_put(nr_node);
293 }
294 
295 #define nr_remove_node_locked(__node) \
296         __nr_remove_node(__node)
297 
298 static void nr_remove_node(struct nr_node *nr_node)
299 {
300         spin_lock_bh(&nr_node_list_lock);
301         __nr_remove_node(nr_node);
302         spin_unlock_bh(&nr_node_list_lock);
303 }
304 
305 static inline void __nr_remove_neigh(struct nr_neigh *nr_neigh)
306 {
307         hlist_del_init(&nr_neigh->neigh_node);
308         nr_neigh_put(nr_neigh);
309 }
310 
311 #define nr_remove_neigh_locked(__neigh) \
312         __nr_remove_neigh(__neigh)
313 
314 static void nr_remove_neigh(struct nr_neigh *nr_neigh)
315 {
316         spin_lock_bh(&nr_neigh_list_lock);
317         __nr_remove_neigh(nr_neigh);
318         spin_unlock_bh(&nr_neigh_list_lock);
319 }
320 
321 /*
322  *      "Delete" a node. Strictly speaking remove a route to a node. The node
323  *      is only deleted if no routes are left to it.
324  */
325 static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct net_device *dev)
326 {
327         struct nr_node  *nr_node;
328         struct nr_neigh *nr_neigh;
329         int i;
330 
331         nr_node = nr_node_get(callsign);
332 
333         if (nr_node == NULL)
334                 return -EINVAL;
335 
336         nr_neigh = nr_neigh_get_dev(neighbour, dev);
337 
338         if (nr_neigh == NULL) {
339                 nr_node_put(nr_node);
340                 return -EINVAL;
341         }
342 
343         nr_node_lock(nr_node);
344         for (i = 0; i < nr_node->count; i++) {
345                 if (nr_node->routes[i].neighbour == nr_neigh) {
346                         nr_neigh->count--;
347                         nr_neigh_put(nr_neigh);
348 
349                         if (nr_neigh->count == 0 && !nr_neigh->locked)
350                                 nr_remove_neigh(nr_neigh);
351                         nr_neigh_put(nr_neigh);
352 
353                         nr_node->count--;
354 
355                         if (nr_node->count == 0) {
356                                 nr_remove_node(nr_node);
357                         } else {
358                                 switch (i) {
359                                 case 0:
360                                         nr_node->routes[0] = nr_node->routes[1];
361                                         /* fall through */
362                                 case 1:
363                                         nr_node->routes[1] = nr_node->routes[2];
364                                 case 2:
365                                         break;
366                                 }
367                                 nr_node_put(nr_node);
368                         }
369                         nr_node_unlock(nr_node);
370 
371                         return 0;
372                 }
373         }
374         nr_neigh_put(nr_neigh);
375         nr_node_unlock(nr_node);
376         nr_node_put(nr_node);
377 
378         return -EINVAL;
379 }
380 
381 /*
382  *      Lock a neighbour with a quality.
383  */
384 static int __must_check nr_add_neigh(ax25_address *callsign,
385         ax25_digi *ax25_digi, struct net_device *dev, unsigned int quality)
386 {
387         struct nr_neigh *nr_neigh;
388 
389         nr_neigh = nr_neigh_get_dev(callsign, dev);
390         if (nr_neigh) {
391                 nr_neigh->quality = quality;
392                 nr_neigh->locked  = 1;
393                 nr_neigh_put(nr_neigh);
394                 return 0;
395         }
396 
397         if ((nr_neigh = kmalloc(sizeof(*nr_neigh), GFP_ATOMIC)) == NULL)
398                 return -ENOMEM;
399 
400         nr_neigh->callsign = *callsign;
401         nr_neigh->digipeat = NULL;
402         nr_neigh->ax25     = NULL;
403         nr_neigh->dev      = dev;
404         nr_neigh->quality  = quality;
405         nr_neigh->locked   = 1;
406         nr_neigh->count    = 0;
407         nr_neigh->number   = nr_neigh_no++;
408         nr_neigh->failed   = 0;
409         refcount_set(&nr_neigh->refcount, 1);
410 
411         if (ax25_digi != NULL && ax25_digi->ndigi > 0) {
412                 nr_neigh->digipeat = kmemdup(ax25_digi, sizeof(*ax25_digi),
413                                              GFP_KERNEL);
414                 if (nr_neigh->digipeat == NULL) {
415                         kfree(nr_neigh);
416                         return -ENOMEM;
417                 }
418         }
419 
420         spin_lock_bh(&nr_neigh_list_lock);
421         hlist_add_head(&nr_neigh->neigh_node, &nr_neigh_list);
422         /* refcount is initialized at 1 */
423         spin_unlock_bh(&nr_neigh_list_lock);
424 
425         return 0;
426 }
427 
428 /*
429  *      "Delete" a neighbour. The neighbour is only removed if the number
430  *      of nodes that may use it is zero.
431  */
432 static int nr_del_neigh(ax25_address *callsign, struct net_device *dev, unsigned int quality)
433 {
434         struct nr_neigh *nr_neigh;
435 
436         nr_neigh = nr_neigh_get_dev(callsign, dev);
437 
438         if (nr_neigh == NULL) return -EINVAL;
439 
440         nr_neigh->quality = quality;
441         nr_neigh->locked  = 0;
442 
443         if (nr_neigh->count == 0)
444                 nr_remove_neigh(nr_neigh);
445         nr_neigh_put(nr_neigh);
446 
447         return 0;
448 }
449 
450 /*
451  *      Decrement the obsolescence count by one. If a route is reduced to a
452  *      count of zero, remove it. Also remove any unlocked neighbours with
453  *      zero nodes routing via it.
454  */
455 static int nr_dec_obs(void)
456 {
457         struct nr_neigh *nr_neigh;
458         struct nr_node  *s;
459         struct hlist_node *nodet;
460         int i;
461 
462         spin_lock_bh(&nr_node_list_lock);
463         nr_node_for_each_safe(s, nodet, &nr_node_list) {
464                 nr_node_lock(s);
465                 for (i = 0; i < s->count; i++) {
466                         switch (s->routes[i].obs_count) {
467                         case 0:         /* A locked entry */
468                                 break;
469 
470                         case 1:         /* From 1 -> 0 */
471                                 nr_neigh = s->routes[i].neighbour;
472 
473                                 nr_neigh->count--;
474                                 nr_neigh_put(nr_neigh);
475 
476                                 if (nr_neigh->count == 0 && !nr_neigh->locked)
477                                         nr_remove_neigh(nr_neigh);
478 
479                                 s->count--;
480 
481                                 switch (i) {
482                                 case 0:
483                                         s->routes[0] = s->routes[1];
484                                         /* Fallthrough */
485                                 case 1:
486                                         s->routes[1] = s->routes[2];
487                                 case 2:
488                                         break;
489                                 }
490                                 break;
491 
492                         default:
493                                 s->routes[i].obs_count--;
494                                 break;
495 
496                         }
497                 }
498 
499                 if (s->count <= 0)
500                         nr_remove_node_locked(s);
501                 nr_node_unlock(s);
502         }
503         spin_unlock_bh(&nr_node_list_lock);
504 
505         return 0;
506 }
507 
508 /*
509  *      A device has been removed. Remove its routes and neighbours.
510  */
511 void nr_rt_device_down(struct net_device *dev)
512 {
513         struct nr_neigh *s;
514         struct hlist_node *nodet, *node2t;
515         struct nr_node  *t;
516         int i;
517 
518         spin_lock_bh(&nr_neigh_list_lock);
519         nr_neigh_for_each_safe(s, nodet, &nr_neigh_list) {
520                 if (s->dev == dev) {
521                         spin_lock_bh(&nr_node_list_lock);
522                         nr_node_for_each_safe(t, node2t, &nr_node_list) {
523                                 nr_node_lock(t);
524                                 for (i = 0; i < t->count; i++) {
525                                         if (t->routes[i].neighbour == s) {
526                                                 t->count--;
527 
528                                                 switch (i) {
529                                                 case 0:
530                                                         t->routes[0] = t->routes[1];
531                                                         /* fall through */
532                                                 case 1:
533                                                         t->routes[1] = t->routes[2];
534                                                 case 2:
535                                                         break;
536                                                 }
537                                         }
538                                 }
539 
540                                 if (t->count <= 0)
541                                         nr_remove_node_locked(t);
542                                 nr_node_unlock(t);
543                         }
544                         spin_unlock_bh(&nr_node_list_lock);
545 
546                         nr_remove_neigh_locked(s);
547                 }
548         }
549         spin_unlock_bh(&nr_neigh_list_lock);
550 }
551 
552 /*
553  *      Check that the device given is a valid AX.25 interface that is "up".
554  *      Or a valid ethernet interface with an AX.25 callsign binding.
555  */
556 static struct net_device *nr_ax25_dev_get(char *devname)
557 {
558         struct net_device *dev;
559 
560         if ((dev = dev_get_by_name(&init_net, devname)) == NULL)
561                 return NULL;
562 
563         if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25)
564                 return dev;
565 
566         dev_put(dev);
567         return NULL;
568 }
569 
570 /*
571  *      Find the first active NET/ROM device, usually "nr0".
572  */
573 struct net_device *nr_dev_first(void)
574 {
575         struct net_device *dev, *first = NULL;
576 
577         rcu_read_lock();
578         for_each_netdev_rcu(&init_net, dev) {
579                 if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM)
580                         if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
581                                 first = dev;
582         }
583         if (first)
584                 dev_hold(first);
585         rcu_read_unlock();
586 
587         return first;
588 }
589 
590 /*
591  *      Find the NET/ROM device for the given callsign.
592  */
593 struct net_device *nr_dev_get(ax25_address *addr)
594 {
595         struct net_device *dev;
596 
597         rcu_read_lock();
598         for_each_netdev_rcu(&init_net, dev) {
599                 if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM &&
600                     ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) {
601                         dev_hold(dev);
602                         goto out;
603                 }
604         }
605         dev = NULL;
606 out:
607         rcu_read_unlock();
608         return dev;
609 }
610 
611 static ax25_digi *nr_call_to_digi(ax25_digi *digi, int ndigis,
612         ax25_address *digipeaters)
613 {
614         int i;
615 
616         if (ndigis == 0)
617                 return NULL;
618 
619         for (i = 0; i < ndigis; i++) {
620                 digi->calls[i]    = digipeaters[i];
621                 digi->repeated[i] = 0;
622         }
623 
624         digi->ndigi      = ndigis;
625         digi->lastrepeat = -1;
626 
627         return digi;
628 }
629 
630 /*
631  *      Handle the ioctls that control the routing functions.
632  */
633 int nr_rt_ioctl(unsigned int cmd, void __user *arg)
634 {
635         struct nr_route_struct nr_route;
636         struct net_device *dev;
637         ax25_digi digi;
638         int ret;
639 
640         switch (cmd) {
641         case SIOCADDRT:
642                 if (copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct)))
643                         return -EFAULT;
644                 if (nr_route.ndigis > AX25_MAX_DIGIS)
645                         return -EINVAL;
646                 if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)
647                         return -EINVAL;
648                 switch (nr_route.type) {
649                 case NETROM_NODE:
650                         if (strnlen(nr_route.mnemonic, 7) == 7) {
651                                 ret = -EINVAL;
652                                 break;
653                         }
654 
655                         ret = nr_add_node(&nr_route.callsign,
656                                 nr_route.mnemonic,
657                                 &nr_route.neighbour,
658                                 nr_call_to_digi(&digi, nr_route.ndigis,
659                                                 nr_route.digipeaters),
660                                 dev, nr_route.quality,
661                                 nr_route.obs_count);
662                         break;
663                 case NETROM_NEIGH:
664                         ret = nr_add_neigh(&nr_route.callsign,
665                                 nr_call_to_digi(&digi, nr_route.ndigis,
666                                                 nr_route.digipeaters),
667                                 dev, nr_route.quality);
668                         break;
669                 default:
670                         ret = -EINVAL;
671                 }
672                 dev_put(dev);
673                 return ret;
674 
675         case SIOCDELRT:
676                 if (copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct)))
677                         return -EFAULT;
678                 if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)
679                         return -EINVAL;
680                 switch (nr_route.type) {
681                 case NETROM_NODE:
682                         ret = nr_del_node(&nr_route.callsign,
683                                 &nr_route.neighbour, dev);
684                         break;
685                 case NETROM_NEIGH:
686                         ret = nr_del_neigh(&nr_route.callsign,
687                                 dev, nr_route.quality);
688                         break;
689                 default:
690                         ret = -EINVAL;
691                 }
692                 dev_put(dev);
693                 return ret;
694 
695         case SIOCNRDECOBS:
696                 return nr_dec_obs();
697 
698         default:
699                 return -EINVAL;
700         }
701 
702         return 0;
703 }
704 
705 /*
706  *      A level 2 link has timed out, therefore it appears to be a poor link,
707  *      then don't use that neighbour until it is reset.
708  */
709 void nr_link_failed(ax25_cb *ax25, int reason)
710 {
711         struct nr_neigh *s, *nr_neigh = NULL;
712         struct nr_node  *nr_node = NULL;
713 
714         spin_lock_bh(&nr_neigh_list_lock);
715         nr_neigh_for_each(s, &nr_neigh_list) {
716                 if (s->ax25 == ax25) {
717                         nr_neigh_hold(s);
718                         nr_neigh = s;
719                         break;
720                 }
721         }
722         spin_unlock_bh(&nr_neigh_list_lock);
723 
724         if (nr_neigh == NULL)
725                 return;
726 
727         nr_neigh->ax25 = NULL;
728         ax25_cb_put(ax25);
729 
730         if (++nr_neigh->failed < sysctl_netrom_link_fails_count) {
731                 nr_neigh_put(nr_neigh);
732                 return;
733         }
734         spin_lock_bh(&nr_node_list_lock);
735         nr_node_for_each(nr_node, &nr_node_list) {
736                 nr_node_lock(nr_node);
737                 if (nr_node->which < nr_node->count &&
738                     nr_node->routes[nr_node->which].neighbour == nr_neigh)
739                         nr_node->which++;
740                 nr_node_unlock(nr_node);
741         }
742         spin_unlock_bh(&nr_node_list_lock);
743         nr_neigh_put(nr_neigh);
744 }
745 
746 /*
747  *      Route a frame to an appropriate AX.25 connection. A NULL ax25_cb
748  *      indicates an internally generated frame.
749  */
750 int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
751 {
752         ax25_address *nr_src, *nr_dest;
753         struct nr_neigh *nr_neigh;
754         struct nr_node  *nr_node;
755         struct net_device *dev;
756         unsigned char *dptr;
757         ax25_cb *ax25s;
758         int ret;
759         struct sk_buff *skbn;
760 
761 
762         nr_src  = (ax25_address *)(skb->data + 0);
763         nr_dest = (ax25_address *)(skb->data + 7);
764 
765         if (ax25 != NULL) {
766                 ret = nr_add_node(nr_src, "", &ax25->dest_addr, ax25->digipeat,
767                                   ax25->ax25_dev->dev, 0,
768                                   sysctl_netrom_obsolescence_count_initialiser);
769                 if (ret)
770                         return ret;
771         }
772 
773         if ((dev = nr_dev_get(nr_dest)) != NULL) {      /* Its for me */
774                 if (ax25 == NULL)                       /* Its from me */
775                         ret = nr_loopback_queue(skb);
776                 else
777                         ret = nr_rx_frame(skb, dev);
778                 dev_put(dev);
779                 return ret;
780         }
781 
782         if (!sysctl_netrom_routing_control && ax25 != NULL)
783                 return 0;
784 
785         /* Its Time-To-Live has expired */
786         if (skb->data[14] == 1) {
787                 return 0;
788         }
789 
790         nr_node = nr_node_get(nr_dest);
791         if (nr_node == NULL)
792                 return 0;
793         nr_node_lock(nr_node);
794 
795         if (nr_node->which >= nr_node->count) {
796                 nr_node_unlock(nr_node);
797                 nr_node_put(nr_node);
798                 return 0;
799         }
800 
801         nr_neigh = nr_node->routes[nr_node->which].neighbour;
802 
803         if ((dev = nr_dev_first()) == NULL) {
804                 nr_node_unlock(nr_node);
805                 nr_node_put(nr_node);
806                 return 0;
807         }
808 
809         /* We are going to change the netrom headers so we should get our
810            own skb, we also did not know until now how much header space
811            we had to reserve... - RXQ */
812         if ((skbn=skb_copy_expand(skb, dev->hard_header_len, 0, GFP_ATOMIC)) == NULL) {
813                 nr_node_unlock(nr_node);
814                 nr_node_put(nr_node);
815                 dev_put(dev);
816                 return 0;
817         }
818         kfree_skb(skb);
819         skb=skbn;
820         skb->data[14]--;
821 
822         dptr  = skb_push(skb, 1);
823         *dptr = AX25_P_NETROM;
824 
825         ax25s = nr_neigh->ax25;
826         nr_neigh->ax25 = ax25_send_frame(skb, 256,
827                                          (ax25_address *)dev->dev_addr,
828                                          &nr_neigh->callsign,
829                                          nr_neigh->digipeat, nr_neigh->dev);
830         if (ax25s)
831                 ax25_cb_put(ax25s);
832 
833         dev_put(dev);
834         ret = (nr_neigh->ax25 != NULL);
835         nr_node_unlock(nr_node);
836         nr_node_put(nr_node);
837 
838         return ret;
839 }
840 
841 #ifdef CONFIG_PROC_FS
842 
843 static void *nr_node_start(struct seq_file *seq, loff_t *pos)
844 {
845         spin_lock_bh(&nr_node_list_lock);
846         return seq_hlist_start_head(&nr_node_list, *pos);
847 }
848 
849 static void *nr_node_next(struct seq_file *seq, void *v, loff_t *pos)
850 {
851         return seq_hlist_next(v, &nr_node_list, pos);
852 }
853 
854 static void nr_node_stop(struct seq_file *seq, void *v)
855 {
856         spin_unlock_bh(&nr_node_list_lock);
857 }
858 
859 static int nr_node_show(struct seq_file *seq, void *v)
860 {
861         char buf[11];
862         int i;
863 
864         if (v == SEQ_START_TOKEN)
865                 seq_puts(seq,
866                          "callsign  mnemonic w n qual obs neigh qual obs neigh qual obs neigh\n");
867         else {
868                 struct nr_node *nr_node = hlist_entry(v, struct nr_node,
869                                                       node_node);
870 
871                 nr_node_lock(nr_node);
872                 seq_printf(seq, "%-9s %-7s  %d %d",
873                         ax2asc(buf, &nr_node->callsign),
874                         (nr_node->mnemonic[0] == '\0') ? "*" : nr_node->mnemonic,
875                         nr_node->which + 1,
876                         nr_node->count);
877 
878                 for (i = 0; i < nr_node->count; i++) {
879                         seq_printf(seq, "  %3d   %d %05d",
880                                 nr_node->routes[i].quality,
881                                 nr_node->routes[i].obs_count,
882                                 nr_node->routes[i].neighbour->number);
883                 }
884                 nr_node_unlock(nr_node);
885 
886                 seq_puts(seq, "\n");
887         }
888         return 0;
889 }
890 
891 static const struct seq_operations nr_node_seqops = {
892         .start = nr_node_start,
893         .next = nr_node_next,
894         .stop = nr_node_stop,
895         .show = nr_node_show,
896 };
897 
898 static int nr_node_info_open(struct inode *inode, struct file *file)
899 {
900         return seq_open(file, &nr_node_seqops);
901 }
902 
903 const struct file_operations nr_nodes_fops = {
904         .owner = THIS_MODULE,
905         .open = nr_node_info_open,
906         .read = seq_read,
907         .llseek = seq_lseek,
908         .release = seq_release,
909 };
910 
911 static void *nr_neigh_start(struct seq_file *seq, loff_t *pos)
912 {
913         spin_lock_bh(&nr_neigh_list_lock);
914         return seq_hlist_start_head(&nr_neigh_list, *pos);
915 }
916 
917 static void *nr_neigh_next(struct seq_file *seq, void *v, loff_t *pos)
918 {
919         return seq_hlist_next(v, &nr_neigh_list, pos);
920 }
921 
922 static void nr_neigh_stop(struct seq_file *seq, void *v)
923 {
924         spin_unlock_bh(&nr_neigh_list_lock);
925 }
926 
927 static int nr_neigh_show(struct seq_file *seq, void *v)
928 {
929         char buf[11];
930         int i;
931 
932         if (v == SEQ_START_TOKEN)
933                 seq_puts(seq, "addr  callsign  dev  qual lock count failed digipeaters\n");
934         else {
935                 struct nr_neigh *nr_neigh;
936 
937                 nr_neigh = hlist_entry(v, struct nr_neigh, neigh_node);
938                 seq_printf(seq, "%05d %-9s %-4s  %3d    %d   %3d    %3d",
939                         nr_neigh->number,
940                         ax2asc(buf, &nr_neigh->callsign),
941                         nr_neigh->dev ? nr_neigh->dev->name : "???",
942                         nr_neigh->quality,
943                         nr_neigh->locked,
944                         nr_neigh->count,
945                         nr_neigh->failed);
946 
947                 if (nr_neigh->digipeat != NULL) {
948                         for (i = 0; i < nr_neigh->digipeat->ndigi; i++)
949                                 seq_printf(seq, " %s",
950                                            ax2asc(buf, &nr_neigh->digipeat->calls[i]));
951                 }
952 
953                 seq_puts(seq, "\n");
954         }
955         return 0;
956 }
957 
958 static const struct seq_operations nr_neigh_seqops = {
959         .start = nr_neigh_start,
960         .next = nr_neigh_next,
961         .stop = nr_neigh_stop,
962         .show = nr_neigh_show,
963 };
964 
965 static int nr_neigh_info_open(struct inode *inode, struct file *file)
966 {
967         return seq_open(file, &nr_neigh_seqops);
968 }
969 
970 const struct file_operations nr_neigh_fops = {
971         .owner = THIS_MODULE,
972         .open = nr_neigh_info_open,
973         .read = seq_read,
974         .llseek = seq_lseek,
975         .release = seq_release,
976 };
977 
978 #endif
979 
980 /*
981  *      Free all memory associated with the nodes and routes lists.
982  */
983 void __exit nr_rt_free(void)
984 {
985         struct nr_neigh *s = NULL;
986         struct nr_node  *t = NULL;
987         struct hlist_node *nodet;
988 
989         spin_lock_bh(&nr_neigh_list_lock);
990         spin_lock_bh(&nr_node_list_lock);
991         nr_node_for_each_safe(t, nodet, &nr_node_list) {
992                 nr_node_lock(t);
993                 nr_remove_node_locked(t);
994                 nr_node_unlock(t);
995         }
996         nr_neigh_for_each_safe(s, nodet, &nr_neigh_list) {
997                 while(s->count) {
998                         s->count--;
999                         nr_neigh_put(s);
1000                 }
1001                 nr_remove_neigh_locked(s);
1002         }
1003         spin_unlock_bh(&nr_node_list_lock);
1004         spin_unlock_bh(&nr_neigh_list_lock);
1005 }
1006 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp