root/net/ax25/ax25_route.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ax25_rt_rx_frame
  2. ax25_rt_device_down
  3. ax25_rt_get_info
  4. ax25_cs_get_info
  5. ax25_rt_autobind
  6. ax25_ip_mode_set
  7. ax25_ip_mode_get

   1 /*
   2  *      AX.25 release 029
   3  *
   4  *      This is ALPHA test software. This code may break your machine, randomly fail to work with new 
   5  *      releases, misbehave and/or generally screw up. It might even work. 
   6  *
   7  *      This code REQUIRES 1.2.1 or higher/ NET3.029
   8  *
   9  *      This module:
  10  *              This module is free software; you can redistribute it and/or
  11  *              modify it under the terms of the GNU General Public License
  12  *              as published by the Free Software Foundation; either version
  13  *              2 of the License, or (at your option) any later version.
  14  *
  15  *      Other kernels modules in this kit are generally BSD derived. See the copyright headers.
  16  *
  17  *
  18  *      History
  19  *      AX.25 020       Jonathan(G4KLX) First go.
  20  *      AX.25 022       Jonathan(G4KLX) Added the actual meat to this - we now have a nice mheard list.
  21  *      AX.25 025       Alan(GW4PTS)    First cut at autobinding by route scan.
  22  *      AX.25 028b      Jonathan(G4KLX) Extracted AX25 control block from the
  23  *                                      sock structure. Device removal now
  24  *                                      removes the heard structure.
  25  *      AX.25 029       Steven(GW7RRM)  Added /proc information for uid/callsign mapping.
  26  *                      Jonathan(G4KLX) Handling of IP mode in the routing list and /proc entry.
  27  */
  28  
  29 #include <linux/config.h>
  30 #ifdef CONFIG_AX25
  31 #include <linux/errno.h>
  32 #include <linux/types.h>
  33 #include <linux/socket.h>
  34 #include <linux/in.h>
  35 #include <linux/kernel.h>
  36 #include <linux/sched.h>
  37 #include <linux/timer.h>
  38 #include <linux/string.h>
  39 #include <linux/sockios.h>
  40 #include <linux/net.h>
  41 #include <net/ax25.h>
  42 #include <linux/inet.h>
  43 #include <linux/netdevice.h>
  44 #include <linux/skbuff.h>
  45 #include <net/sock.h>
  46 #include <asm/segment.h>
  47 #include <asm/system.h>
  48 #include <linux/fcntl.h>
  49 #include <linux/mm.h>
  50 #include <linux/interrupt.h>
  51 
  52 #define AX25_ROUTE_MAX  40
  53 
  54 static struct ax25_route {
  55         struct ax25_route *next;
  56         ax25_address callsign;
  57         struct device *dev;
  58         struct timeval stamp;
  59         int n;
  60         char ip_mode;
  61 } *ax25_route = NULL;
  62 
  63 void ax25_rt_rx_frame(ax25_address *src, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  64 {
  65         unsigned long flags;
  66         extern struct timeval xtime;
  67         struct ax25_route *ax25_rt;
  68         struct ax25_route *oldest;
  69         int count;
  70 
  71         count  = 0;
  72         oldest = NULL;
  73 
  74         for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
  75                 if (count == 0 || ax25_rt->stamp.tv_sec < oldest->stamp.tv_sec)
  76                         oldest = ax25_rt;
  77                 
  78                 if (ax25cmp(&ax25_rt->callsign, src) == 0 && ax25_rt->dev == dev) {
  79                         ax25_rt->stamp = xtime;
  80                         ax25_rt->n++;
  81                         return;                 
  82                 }
  83 
  84                 count++;
  85         }
  86 
  87         if (count > AX25_ROUTE_MAX) {
  88                 oldest->callsign = *src;
  89                 oldest->dev      = dev;
  90                 oldest->stamp    = xtime;
  91                 oldest->n        = 1;
  92                 oldest->ip_mode  = ' ';
  93                 return;
  94         }
  95 
  96         if ((ax25_rt = (struct ax25_route *)kmalloc(sizeof(struct ax25_route), GFP_ATOMIC)) == NULL)
  97                 return;         /* No space */
  98 
  99         ax25_rt->callsign = *src;
 100         ax25_rt->dev      = dev;
 101         ax25_rt->stamp    = xtime;
 102         ax25_rt->n        = 1;
 103         ax25_rt->ip_mode  = ' ';
 104 
 105         save_flags(flags);
 106         cli();
 107 
 108         ax25_rt->next = ax25_route;
 109         ax25_route    = ax25_rt;
 110 
 111         restore_flags(flags);
 112 }
 113 
 114 void ax25_rt_device_down(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 115 {
 116         struct ax25_route *s, *t, *ax25_rt = ax25_route;
 117         
 118         while (ax25_rt != NULL) {
 119                 s       = ax25_rt;
 120                 ax25_rt = ax25_rt->next;
 121 
 122                 if (s->dev == dev) {
 123                         if (ax25_route == s) {
 124                                 ax25_route = s->next;
 125                                 kfree_s((void *)s, (sizeof *s));
 126                         } else {
 127                                 for (t = ax25_route; t != NULL; t = t->next) {
 128                                         if (t->next == s) {
 129                                                 t->next = s->next;
 130                                                 kfree_s((void *)s, sizeof(*s));
 131                                                 break;
 132                                         }
 133                                 }                               
 134                         }
 135                 }
 136         }
 137 }
 138 
 139 int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length)
     /* [previous][next][first][last][top][bottom][index][help] */
 140 {
 141         struct ax25_route *ax25_rt;
 142         int len     = 0;
 143         off_t pos   = 0;
 144         off_t begin = 0;
 145   
 146         cli();
 147 
 148         len += sprintf(buffer, "callsign  dev  count time      mode\n");
 149 
 150         for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
 151                 len += sprintf(buffer + len, "%-9s %-4s %5d %9d",
 152                         ax2asc(&ax25_rt->callsign),
 153                         ax25_rt->dev ? ax25_rt->dev->name : "???",
 154                         ax25_rt->n,
 155                         ax25_rt->stamp.tv_sec);
 156 
 157                 switch (ax25_rt->ip_mode) {
 158                         case 'V':
 159                         case 'v':
 160                                 len += sprintf(buffer + len, "   vc\n");
 161                                 break;
 162                         case 'D':
 163                         case 'd':
 164                                 len += sprintf(buffer + len, "   dg\n");
 165                                 break;
 166                         default:
 167                                 len += sprintf(buffer + len, "\n");
 168                                 break;
 169                 }
 170                                 
 171                 pos = begin + len;
 172 
 173                 if (pos < offset) {
 174                         len   = 0;
 175                         begin = pos;
 176                 }
 177                 
 178                 if (pos > offset + length)
 179                         break;
 180         }
 181 
 182         sti();
 183 
 184         *start = buffer + (offset - begin);
 185         len   -= (offset - begin);
 186 
 187         if (len > length) len = length;
 188 
 189         return len;
 190 } 
 191 
 192 int ax25_cs_get_info(char *buffer, char **start, off_t offset, int length)
     /* [previous][next][first][last][top][bottom][index][help] */
 193 {
 194         ax25_uid_assoc *pt;
 195         int len     = 0;
 196         off_t pos   = 0;
 197         off_t begin = 0;
 198 
 199         cli();
 200 
 201         len += sprintf(buffer, "Policy: %d\n", ax25_uid_policy);
 202 
 203         for (pt = ax25_uid_list; pt != NULL; pt = pt->next) {
 204                 len += sprintf(buffer + len, "%6d %s\n", pt->uid, ax2asc(&pt->call));
 205 
 206                 pos = begin + len;
 207 
 208                 if (pos < offset) {
 209                         len = 0;
 210                         begin = pos;
 211                 }
 212 
 213                 if (pos > offset + length)
 214                         break;
 215         }
 216 
 217         sti();
 218 
 219         *start = buffer + (offset - begin);
 220         len   -= offset - begin;
 221 
 222         if (len > length) len = length;
 223 
 224         return len;
 225 }
 226 
 227 /*
 228  *      Find what interface to use.
 229  */
 230 int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 231 {
 232         struct ax25_route *ax25_rt;
 233         ax25_address *call;
 234         
 235         for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
 236                 if (ax25cmp(&ax25_rt->callsign, addr) == 0) {
 237                         /*
 238                          *      Bind to the physical interface we heard them on.
 239                          */
 240                         if ((ax25->device = ax25_rt->dev) == NULL)
 241                                 continue;
 242                         if ((call = ax25_findbyuid(current->euid)) == NULL) {
 243                                 if (ax25_uid_policy && !suser())
 244                                         return -EPERM;
 245                                 call = (ax25_address *)ax25->device->dev_addr;
 246                         }
 247                         memcpy(&ax25->source_addr, call, sizeof(ax25_address));
 248                         if (ax25->sk != NULL)
 249                                 ax25->sk->zapped = 0;
 250 
 251                         return 0;                       
 252                 }
 253         }
 254 
 255         return -EINVAL;
 256 }
 257 
 258 /*
 259  *      Register the mode of an incoming IP frame. It is assumed that an entry
 260  *      already exists in the routing table.
 261  */
 262 void ax25_ip_mode_set(ax25_address *callsign, struct device *dev, char ip_mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 263 {
 264         struct ax25_route *ax25_rt;
 265 
 266         for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
 267                 if (ax25cmp(&ax25_rt->callsign, callsign) == 0 && ax25_rt->dev == dev) {
 268                         ax25_rt->ip_mode = ip_mode;
 269                         return;
 270                 }
 271         }
 272 }
 273 
 274 /*
 275  *      Return the IP mode of a given callsign/device pair.
 276  */
 277 char ax25_ip_mode_get(ax25_address *callsign, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 278 {
 279         struct ax25_route *ax25_rt;
 280 
 281         for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next)
 282                 if (ax25cmp(&ax25_rt->callsign, callsign) == 0 && ax25_rt->dev == dev)
 283                         return ax25_rt->ip_mode;
 284 
 285         return ' ';
 286 }
 287 
 288 #endif

/* [previous][next][first][last][top][bottom][index][help] */