root/fs/proc/net.c

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

DEFINITIONS

This source file includes following definitions.
  1. proc_lookupnet
  2. proc_readnetdir
  3. proc_readnet

   1 /*
   2  *  linux/fs/proc/net.c
   3  *
   4  *  Copyright (C) 1991, 1992 Linus Torvalds
   5  *
   6  *  gjh 3/'93 heim@peanuts.informatik.uni-tuebingen.de (Gerald J. Heim)
   7  *            most of this file is stolen from base.c
   8  *            it works, but you shouldn't use it as a guideline
   9  *            for new proc-fs entries. once i'll make it better.
  10  * fvk 3/'93  waltje@uwalt.nl.mugnet.org (Fred N. van Kempen)
  11  *            cleaned up the whole thing, moved "net" specific code to
  12  *            the NET kernel layer (where it belonged in the first place).
  13  * Michael K. Johnson (johnsonm@stolaf.edu) 3/93
  14  *            Added support from my previous inet.c.  Cleaned things up
  15  *            quite a bit, modularized the code.
  16  * fvk 4/'93  waltje@uwalt.nl.mugnet.org (Fred N. van Kempen)
  17  *            Renamed "route_get_info()" to "rt_get_info()" for consistency.
  18  * Alan Cox (gw4pts@gw4pts.ampr.org) 4/94
  19  *            Dusted off the code and added IPX. Fixed the 4K limit.
  20  * Erik Schoenfelder (schoenfr@ibr.cs.tu-bs.de)
  21  *            /proc/net/snmp.
  22  * Alan Cox (gw4pts@gw4pts.ampr.org) 1/95
  23  *            Added Appletalk slots
  24  *
  25  *  proc net directory handling functions
  26  */
  27 #include <linux/autoconf.h>
  28 
  29 #include <asm/segment.h>
  30 
  31 #include <linux/errno.h>
  32 #include <linux/sched.h>
  33 #include <linux/proc_fs.h>
  34 #include <linux/stat.h>
  35 #include <linux/fcntl.h>
  36 #include <linux/config.h>
  37 #include <linux/mm.h>
  38 
  39 /* forward references */
  40 static int proc_readnet(struct inode * inode, struct file * file,
  41                          char * buf, int count);
  42 static int proc_readnetdir(struct inode *, struct file *,
  43                            void *, filldir_t filldir);
  44 static int proc_lookupnet(struct inode *,const char *,int,struct inode **);
  45 
  46 /* the get_*_info() functions are in the net code, and are configured
  47    in via the standard mechanism... */
  48 extern int unix_get_info(char *, char **, off_t, int);
  49 #ifdef CONFIG_INET
  50 extern int tcp_get_info(char *, char **, off_t, int);
  51 extern int udp_get_info(char *, char **, off_t, int);
  52 extern int raw_get_info(char *, char **, off_t, int);
  53 extern int arp_get_info(char *, char **, off_t, int);
  54 extern int rarp_get_info(char *, char **, off_t, int);
  55 extern int dev_get_info(char *, char **, off_t, int);
  56 extern int rt_get_info(char *, char **, off_t, int);
  57 extern int snmp_get_info(char *, char **, off_t, int);
  58 extern int afinet_get_info(char *, char **, off_t, int);
  59 #if     defined(CONFIG_WAVELAN)
  60 extern int wavelan_get_info(char *, char **, off_t, int);
  61 #endif  /* defined(CONFIG_WAVELAN) */
  62 #ifdef CONFIG_IP_ACCT
  63 extern int ip_acct_procinfo(char *, char **, off_t, int, int);
  64 #endif /* CONFIG_IP_ACCT */
  65 #ifdef CONFIG_IP_FIREWALL
  66 extern int ip_fw_blk_procinfo(char *, char **, off_t, int, int);
  67 extern int ip_fw_fwd_procinfo(char *, char **, off_t, int, int);
  68 #endif /* CONFIG_IP_FIREWALL */
  69 extern int ip_msqhst_procinfo(char *, char **, off_t, int);
  70 extern int ip_mc_procinfo(char *, char **, off_t, int);
  71 #endif /* CONFIG_INET */
  72 #ifdef CONFIG_IPX
  73 extern int ipx_get_info(char *, char **, off_t, int);
  74 extern int ipx_rt_get_info(char *, char **, off_t, int);
  75 extern int ipx_get_interface_info(char *, char **, off_t , int);
  76 #endif /* CONFIG_IPX */
  77 #ifdef CONFIG_AX25
  78 extern int ax25_get_info(char *, char **, off_t, int);
  79 extern int ax25_rt_get_info(char *, char **, off_t, int);
  80 extern int ax25_cs_get_info(char *, char **, off_t, int);
  81 #ifdef CONFIG_NETROM
  82 extern int nr_get_info(char *, char **, off_t, int);
  83 extern int nr_nodes_get_info(char *, char **, off_t, int);
  84 extern int nr_neigh_get_info(char *, char **, off_t, int);
  85 #endif /* CONFIG_NETROM */
  86 #endif /* CONFIG_AX25 */
  87 #ifdef CONFIG_ATALK
  88 extern int atalk_get_info(char *, char **, off_t, int);
  89 extern int atalk_rt_get_info(char *, char **, off_t, int);
  90 extern int atalk_if_get_info(char *, char **, off_t, int);
  91 #endif
  92 
  93 
  94 static struct file_operations proc_net_operations = {
  95         NULL,                   /* lseek - default */
  96         proc_readnet,           /* read - bad */
  97         NULL,                   /* write - bad */
  98         proc_readnetdir,        /* readdir */
  99         NULL,                   /* select - default */
 100         NULL,                   /* ioctl - default */
 101         NULL,                   /* mmap */
 102         NULL,                   /* no special open code */
 103         NULL,                   /* no special release code */
 104         NULL                    /* can't fsync */
 105 };
 106 
 107 /*
 108  * proc directories can do almost nothing..
 109  */
 110 struct inode_operations proc_net_inode_operations = {
 111         &proc_net_operations,   /* default net directory file-ops */
 112         NULL,                   /* create */
 113         proc_lookupnet,         /* lookup */
 114         NULL,                   /* link */
 115         NULL,                   /* unlink */
 116         NULL,                   /* symlink */
 117         NULL,                   /* mkdir */
 118         NULL,                   /* rmdir */
 119         NULL,                   /* mknod */
 120         NULL,                   /* rename */
 121         NULL,                   /* readlink */
 122         NULL,                   /* follow_link */
 123         NULL,                   /* bmap */
 124         NULL,                   /* truncate */
 125         NULL                    /* permission */
 126 };
 127 
 128 static struct proc_dir_entry net_dir[] = {
 129         { PROC_NET,             1, "." },
 130         { PROC_ROOT_INO,        2, ".." },
 131         { PROC_NET_UNIX,        4, "unix" },
 132 #ifdef CONFIG_INET
 133         { PROC_NET_ARP,         3, "arp" },
 134         { PROC_NET_ROUTE,       5, "route" },
 135         { PROC_NET_DEV,         3, "dev" },
 136         { PROC_NET_RAW,         3, "raw" },
 137         { PROC_NET_TCP,         3, "tcp" },
 138         { PROC_NET_UDP,         3, "udp" },
 139         { PROC_NET_SNMP,        4, "snmp" },
 140         { PROC_NET_SOCKSTAT,    8, "sockstat" },
 141 #ifdef CONFIG_INET_RARP
 142         { PROC_NET_RARP,        4, "rarp"},
 143 #endif
 144 #ifdef CONFIG_IP_MULTICAST
 145         { PROC_NET_IGMP,        4, "igmp"},
 146 #endif
 147 #ifdef CONFIG_IP_FIREWALL
 148         { PROC_NET_IPFWFWD,     10, "ip_forward"},
 149         { PROC_NET_IPFWBLK,     8,  "ip_block"},
 150 #endif
 151 #ifdef CONFIG_IP_MASQUERADE
 152         { PROC_NET_IPMSQHST,    13, "ip_masquerade"},
 153 #endif
 154 #ifdef CONFIG_IP_ACCT
 155         { PROC_NET_IPACCT,      7,  "ip_acct"},
 156 #endif
 157 #if     defined(CONFIG_WAVELAN)
 158         { PROC_NET_WAVELAN,     7, "wavelan" },
 159 #endif  /* defined(CONFIG_WAVELAN) */
 160 #endif  /* CONFIG_INET */
 161 #ifdef CONFIG_IPX
 162         { PROC_NET_IPX_ROUTE,   9, "ipx_route" },
 163         { PROC_NET_IPX,         3, "ipx" },
 164         { PROC_NET_IPX_INTERFACE, 13, "ipx_interface" },
 165 #endif /* CONFIG_IPX */
 166 #ifdef CONFIG_AX25
 167         { PROC_NET_AX25_ROUTE,  10, "ax25_route" },
 168         { PROC_NET_AX25,        4, "ax25" },
 169         { PROC_NET_AX25_CALLS,  10, "ax25_calls" },
 170 #ifdef CONFIG_NETROM
 171         { PROC_NET_NR_NODES,    8, "nr_nodes" },
 172         { PROC_NET_NR_NEIGH,    8, "nr_neigh" },
 173         { PROC_NET_NR,          2, "nr" },
 174 #endif /* CONFIG_NETROM */
 175 #endif /* CONFIG_AX25 */
 176 #ifdef CONFIG_ATALK
 177         { PROC_NET_ATALK,       9, "appletalk" },
 178         { PROC_NET_AT_ROUTE,    11,"atalk_route" },
 179         { PROC_NET_ATIF,        11,"atalk_iface" },
 180 #endif /* CONFIG_ATALK */
 181         { 0, 0, NULL }
 182 };
 183 
 184 #define NR_NET_DIRENTRY ((sizeof (net_dir))/(sizeof (net_dir[0])) - 1)
 185 
 186 static int proc_lookupnet(struct inode * dir,const char * name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 187         struct inode ** result)
 188 {
 189         struct proc_dir_entry *de;
 190 
 191         *result = NULL;
 192         if (!dir)
 193                 return -ENOENT;
 194         if (!S_ISDIR(dir->i_mode)) {
 195                 iput(dir);
 196                 return -ENOENT;
 197         }
 198         for (de = net_dir ; de->name ; de++) {
 199                 if (!proc_match(len, name, de))
 200                         continue;
 201                 *result = iget(dir->i_sb, de->low_ino);
 202                 iput(dir);
 203                 if (!*result)
 204                         return -ENOENT;
 205                 return 0;
 206         }
 207         iput(dir);
 208         return -ENOENT;
 209 }
 210 
 211 static int proc_readnetdir(struct inode * inode, struct file * filp,
     /* [previous][next][first][last][top][bottom][index][help] */
 212         void * dirent, filldir_t filldir)
 213 {
 214         struct proc_dir_entry * de;
 215         unsigned int ino;
 216 
 217         if (!inode || !S_ISDIR(inode->i_mode))
 218                 return -EBADF;
 219         ino = inode->i_ino;
 220         while (((unsigned) filp->f_pos) < NR_NET_DIRENTRY) {
 221                 de = net_dir + filp->f_pos;
 222                 if (filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino) < 0)
 223                         break;
 224                 filp->f_pos++;
 225         }
 226         return 0;
 227 }
 228 
 229 
 230 #define PROC_BLOCK_SIZE (3*1024)                /* 4K page size but our output routines use some slack for overruns */
 231 
 232 static int proc_readnet(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 233                         char * buf, int count)
 234 {
 235         char * page;
 236         int length;
 237         unsigned int ino;
 238         int bytes=count;
 239         int thistime;
 240         int copied=0;
 241         char *start;
 242 
 243         if (count < 0)
 244                 return -EINVAL;
 245         if (!(page = (char*) __get_free_page(GFP_KERNEL)))
 246                 return -ENOMEM;
 247         ino = inode->i_ino;
 248 
 249         while(bytes>0)
 250         {
 251                 thistime=bytes;
 252                 if(bytes>PROC_BLOCK_SIZE)
 253                         thistime=PROC_BLOCK_SIZE;
 254 
 255                 switch (ino) 
 256                 {
 257                         case PROC_NET_UNIX:
 258                                 length = unix_get_info(page,&start,file->f_pos,thistime);
 259                                 break;
 260 #ifdef CONFIG_INET
 261                         case PROC_NET_SOCKSTAT:
 262                                 length = afinet_get_info(page,&start,file->f_pos,thistime);
 263                                 break;
 264                         case PROC_NET_ARP:
 265                                 length = arp_get_info(page,&start,file->f_pos,thistime);
 266                                 break;
 267                         case PROC_NET_ROUTE:
 268                                 length = rt_get_info(page,&start,file->f_pos,thistime);
 269                                 break;
 270                         case PROC_NET_DEV:
 271                                 length = dev_get_info(page,&start,file->f_pos,thistime);
 272                                 break;
 273                         case PROC_NET_RAW:
 274                                 length = raw_get_info(page,&start,file->f_pos,thistime);
 275                                 break;
 276                         case PROC_NET_TCP:
 277                                 length = tcp_get_info(page,&start,file->f_pos,thistime);
 278                                 break;
 279                         case PROC_NET_UDP:
 280                                 length = udp_get_info(page,&start,file->f_pos,thistime);
 281                                 break;
 282                         case PROC_NET_SNMP:
 283                                 length = snmp_get_info(page, &start, file->f_pos,thistime);
 284                                 break;
 285 #ifdef CONFIG_IP_MULTICAST
 286                         case PROC_NET_IGMP:
 287                                 length = ip_mc_procinfo(page, &start, file->f_pos,thistime);
 288                                 break;
 289 #endif
 290 #ifdef CONFIG_IP_FIREWALL
 291                         case PROC_NET_IPFWFWD:
 292                                 length = ip_fw_fwd_procinfo(page, &start, file->f_pos,
 293                                         thistime, (file->f_flags & O_ACCMODE) == O_RDWR);
 294                                 break;
 295                         case PROC_NET_IPFWBLK:
 296                                 length = ip_fw_blk_procinfo(page, &start, file->f_pos,
 297                                         thistime, (file->f_flags & O_ACCMODE) == O_RDWR);
 298                                 break;
 299 #endif
 300 #ifdef CONFIG_IP_ACCT
 301                         case PROC_NET_IPACCT:
 302                                 length = ip_acct_procinfo(page, &start, file->f_pos,
 303                                         thistime, (file->f_flags & O_ACCMODE) == O_RDWR);
 304                                 break;
 305 #endif
 306 #ifdef CONFIG_IP_MASQUERADE
 307                         case PROC_NET_IPMSQHST:
 308                                 length = ip_msqhst_procinfo(page, &start, file->f_pos,thistime);
 309                                 break;
 310 #endif
 311 #ifdef CONFIG_INET_RARP                         
 312                         case PROC_NET_RARP:
 313                                 length = rarp_get_info(page,&start,file->f_pos,thistime);
 314                                 break;
 315 #endif /* CONFIG_INET_RARP */                           
 316 #if     defined(CONFIG_WAVELAN)
 317                         case PROC_NET_WAVELAN:
 318                                 length = wavelan_get_info(page, &start, file->f_pos, thistime);
 319                                 break;
 320 #endif  /* defined(CONFIG_WAVELAN) */
 321 #endif /* CONFIG_INET */
 322 #ifdef CONFIG_IPX
 323                         case PROC_NET_IPX_INTERFACE:
 324                                 length = ipx_get_interface_info(page, &start, file->f_pos, thistime);
 325                                 break;
 326                         case PROC_NET_IPX_ROUTE:
 327                                 length = ipx_rt_get_info(page,&start,file->f_pos,thistime);
 328                                 break;
 329                         case PROC_NET_IPX:
 330                                 length = ipx_get_info(page,&start,file->f_pos,thistime);
 331                                 break;
 332 #endif /* CONFIG_IPX */
 333 #ifdef CONFIG_ATALK
 334                         case PROC_NET_ATALK:
 335                                 length = atalk_get_info(page, &start, file->f_pos, thistime);
 336                                 break;
 337                         case PROC_NET_AT_ROUTE:
 338                                 length = atalk_rt_get_info(page, &start, file->f_pos, thistime);
 339                                 break;
 340                         case PROC_NET_ATIF:
 341                                 length = atalk_if_get_info(page, &start, file->f_pos, thistime);
 342                                 break;
 343 #endif /* CONFIG_ATALK */
 344 #ifdef CONFIG_AX25
 345                         case PROC_NET_AX25_ROUTE:
 346                                 length = ax25_rt_get_info(page,&start,file->f_pos,thistime);
 347                                 break;
 348                         case PROC_NET_AX25:
 349                                 length = ax25_get_info(page,&start,file->f_pos,thistime);
 350                                 break;
 351                         case PROC_NET_AX25_CALLS:
 352                                 length = ax25_cs_get_info(page,&start,file->f_pos,thistime);
 353                                 break;
 354 #ifdef CONFIG_NETROM
 355                         case PROC_NET_NR_NODES:
 356                                 length = nr_nodes_get_info(page,&start,file->f_pos,thistime);
 357                                 break;
 358                         case PROC_NET_NR_NEIGH:
 359                                 length = nr_neigh_get_info(page,&start,file->f_pos,thistime);
 360                                 break;
 361                         case PROC_NET_NR:
 362                                 length = nr_get_info(page,&start,file->f_pos,thistime);
 363                                 break;
 364 #endif /* CONFIG_NETROM */
 365 #endif /* CONFIG_AX25 */
 366 
 367                         default:
 368                                 free_page((unsigned long) page);
 369                                 return -EBADF;
 370                 }
 371                 
 372                 /*
 373                  *      We have been given a non page aligned block of
 374                  *      the data we asked for + a bit. We have been given
 375                  *      the start pointer and we know the length.. 
 376                  */
 377 
 378                 if (length <= 0)
 379                         break;
 380                 /*
 381                  *      Copy the bytes
 382                  */
 383                 memcpy_tofs(buf+copied, start, length);
 384                 file->f_pos+=length;    /* Move down the file */
 385                 bytes-=length;
 386                 copied+=length;
 387                 if(length<thistime)
 388                         break;  /* End of file */
 389         }
 390         free_page((unsigned long) page);
 391         return copied;
 392 
 393 }

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