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  *
  21  *  proc net directory handling functions
  22  */
  23 #include <linux/autoconf.h>
  24 
  25 #include <asm/segment.h>
  26 
  27 #include <linux/errno.h>
  28 #include <linux/sched.h>
  29 #include <linux/proc_fs.h>
  30 #include <linux/stat.h>
  31 
  32 /* forward references */
  33 static int proc_readnet(struct inode * inode, struct file * file,
  34                          char * buf, int count);
  35 static int proc_readnetdir(struct inode *, struct file *,
  36                            struct dirent *, int);
  37 static int proc_lookupnet(struct inode *,const char *,int,struct inode **);
  38 
  39 /* the get_*_info() functions are in the net code, and are configured
  40    in via the standard mechanism... */
  41 extern int unix_get_info(char *, char **, off_t, int);
  42 #ifdef CONFIG_INET
  43 extern int tcp_get_info(char *, char **, off_t, int);
  44 extern int udp_get_info(char *, char **, off_t, int);
  45 extern int raw_get_info(char *, char **, off_t, int);
  46 extern int arp_get_info(char *, char **, off_t, int);
  47 extern int rarp_get_info(char *, char **, off_t, int);
  48 extern int dev_get_info(char *, char **, off_t, int);
  49 extern int rt_get_info(char *, char **, off_t, int);
  50 #endif /* CONFIG_INET */
  51 #ifdef CONFIG_IPX
  52 extern int ipx_get_info(char *, char **, off_t, int);
  53 extern int ipx_rt_get_info(char *, char **, off_t, int);
  54 #endif /* CONFIG_IPX */
  55 #ifdef CONFIG_AX25
  56 extern int ax25_get_info(char *, char **, off_t, int);
  57 extern int ax25_rt_get_info(char *, char **, off_t, int);
  58 #ifdef CONFIG_NETROM
  59 extern int nr_get_info(char *, char **, off_t, int);
  60 extern int nr_nodes_get_info(char *, char **, off_t, int);
  61 extern int nr_neigh_get_info(char *, char **, off_t, int);
  62 #endif /* CONFIG_NETROM */
  63 #endif /* CONFIG_AX25 */
  64 
  65 
  66 static struct file_operations proc_net_operations = {
  67         NULL,                   /* lseek - default */
  68         proc_readnet,           /* read - bad */
  69         NULL,                   /* write - bad */
  70         proc_readnetdir,        /* readdir */
  71         NULL,                   /* select - default */
  72         NULL,                   /* ioctl - default */
  73         NULL,                   /* mmap */
  74         NULL,                   /* no special open code */
  75         NULL,                   /* no special release code */
  76         NULL                    /* can't fsync */
  77 };
  78 
  79 /*
  80  * proc directories can do almost nothing..
  81  */
  82 struct inode_operations proc_net_inode_operations = {
  83         &proc_net_operations,   /* default net directory file-ops */
  84         NULL,                   /* create */
  85         proc_lookupnet,         /* lookup */
  86         NULL,                   /* link */
  87         NULL,                   /* unlink */
  88         NULL,                   /* symlink */
  89         NULL,                   /* mkdir */
  90         NULL,                   /* rmdir */
  91         NULL,                   /* mknod */
  92         NULL,                   /* rename */
  93         NULL,                   /* readlink */
  94         NULL,                   /* follow_link */
  95         NULL,                   /* bmap */
  96         NULL,                   /* truncate */
  97         NULL                    /* permission */
  98 };
  99 
 100 static struct proc_dir_entry net_dir[] = {
 101         { 1,2,".." },
 102         { 8,1,"." },
 103         { 128,4,"unix" }
 104 #ifdef CONFIG_INET
 105         ,{ 129,3,"arp" },
 106         { 130,5,"route" },
 107         { 131,3,"dev" },
 108         { 132,3,"raw" },
 109         { 133,3,"tcp" },
 110         { 134,3,"udp" }
 111 #ifdef CONFIG_INET_RARP
 112         ,{ 135,4,"rarp"}
 113 #endif
 114 #endif  /* CONFIG_INET */
 115 #ifdef CONFIG_IPX
 116         ,{ 136,9,"ipx_route" },
 117         { 137,3,"ipx" }
 118 #endif /* CONFIG_IPX */
 119 #ifdef CONFIG_AX25
 120         ,{ 138,10,"ax25_route" },
 121         { 139,4,"ax25" }
 122 #ifdef CONFIG_NETROM
 123         ,{ 140,8,"nr_nodes" },
 124         { 141,8,"nr_neigh" },
 125         { 142,2,"nr" }
 126 #endif /* CONFIG_NETROM */
 127 #endif /* CONFIG_AX25 */
 128 };
 129 
 130 #define NR_NET_DIRENTRY ((sizeof (net_dir))/(sizeof (net_dir[0])))
 131 
 132 
 133 static int proc_lookupnet(struct inode * dir,const char * name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 134         struct inode ** result)
 135 {
 136         unsigned int ino;
 137         int i;
 138 
 139         *result = NULL;
 140         if (!dir)
 141                 return -ENOENT;
 142         if (!S_ISDIR(dir->i_mode)) {
 143                 iput(dir);
 144                 return -ENOENT;
 145         }
 146         i = NR_NET_DIRENTRY;
 147         while (i-- > 0 && !proc_match(len,name,net_dir+i))
 148                 /* nothing */;
 149         if (i < 0) {
 150                 iput(dir);
 151                 return -ENOENT;
 152         }
 153         ino = net_dir[i].low_ino;
 154         if (!(*result = iget(dir->i_sb,ino))) {
 155                 iput(dir);
 156                 return -ENOENT;
 157         }
 158         iput(dir);
 159         return 0;
 160 }
 161 
 162 static int proc_readnetdir(struct inode * inode, struct file * filp,
     /* [previous][next][first][last][top][bottom][index][help] */
 163         struct dirent * dirent, int count)
 164 {
 165         struct proc_dir_entry * de;
 166         unsigned int ino;
 167         int i,j;
 168 
 169         if (!inode || !S_ISDIR(inode->i_mode))
 170                 return -EBADF;
 171         ino = inode->i_ino;
 172         if (((unsigned) filp->f_pos) < NR_NET_DIRENTRY) {
 173                 de = net_dir + filp->f_pos;
 174                 filp->f_pos++;
 175                 i = de->namelen;
 176                 ino = de->low_ino;
 177                 put_fs_long(ino, &dirent->d_ino);
 178                 put_fs_word(i,&dirent->d_reclen);
 179                 put_fs_byte(0,i+dirent->d_name);
 180                 j = i;
 181                 while (i--)
 182                         put_fs_byte(de->name[i], i+dirent->d_name);
 183                 return j;
 184         }
 185         return 0;
 186 }
 187 
 188 
 189 #define PROC_BLOCK_SIZE (3*1024)                /* 4K page size but our output routines use some slack for overruns */
 190 
 191 static int proc_readnet(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 192                         char * buf, int count)
 193 {
 194         char * page;
 195         int length;
 196         unsigned int ino;
 197         int bytes=count;
 198         int thistime;
 199         int copied=0;
 200         char *start;
 201 
 202         if (count < 0)
 203                 return -EINVAL;
 204         if (!(page = (char*) __get_free_page(GFP_KERNEL)))
 205                 return -ENOMEM;
 206         ino = inode->i_ino;
 207 
 208         while(bytes>0)
 209         {
 210                 thistime=bytes;
 211                 if(bytes>PROC_BLOCK_SIZE)
 212                         thistime=PROC_BLOCK_SIZE;
 213 
 214                 switch (ino) 
 215                 {
 216                         case 128:
 217                                 length = unix_get_info(page,&start,file->f_pos,thistime);
 218                                 break;
 219 #ifdef CONFIG_INET
 220                         case 129:
 221                                 length = arp_get_info(page,&start,file->f_pos,thistime);
 222                                 break;
 223                         case 130:
 224                                 length = rt_get_info(page,&start,file->f_pos,thistime);
 225                                 break;
 226                         case 131:
 227                                 length = dev_get_info(page,&start,file->f_pos,thistime);
 228                                 break;
 229                         case 132:
 230                                 length = raw_get_info(page,&start,file->f_pos,thistime);
 231                                 break;
 232                         case 133:
 233                                 length = tcp_get_info(page,&start,file->f_pos,thistime);
 234                                 break;
 235                         case 134:
 236                                 length = udp_get_info(page,&start,file->f_pos,thistime);
 237                                 break;
 238 #ifdef CONFIG_INET_RARP                         
 239                         case 135:
 240                                 length = rarp_get_info(page,&start,file->f_pos,thistime);
 241                                 break;
 242 #endif /* CONFIG_INET_RARP */                           
 243 #endif /* CONFIG_INET */
 244 #ifdef CONFIG_IPX
 245                         case 136:
 246                                 length = ipx_rt_get_info(page,&start,file->f_pos,thistime);
 247                                 break;
 248                         case 137:
 249                                 length = ipx_get_info(page,&start,file->f_pos,thistime);
 250                                 break;
 251 #endif /* CONFIG_IPX */
 252 #ifdef CONFIG_AX25
 253                         case 138:
 254                                 length = ax25_rt_get_info(page,&start,file->f_pos,thistime);
 255                                 break;
 256                         case 139:
 257                                 length = ax25_get_info(page,&start,file->f_pos,thistime);
 258                                 break;
 259 #ifdef CONFIG_NETROM
 260                         case 140:
 261                                 length = nr_nodes_get_info(page,&start,file->f_pos,thistime);
 262                                 break;
 263                         case 141:
 264                                 length = nr_neigh_get_info(page,&start,file->f_pos,thistime);
 265                                 break;
 266                         case 142:
 267                                 length = nr_get_info(page,&start,file->f_pos,thistime);
 268                                 break;
 269 #endif /* CONFIG_NETROM */
 270 #endif /* CONFIG_AX25 */
 271 
 272                         default:
 273                                 free_page((unsigned long) page);
 274                                 return -EBADF;
 275                 }
 276                 
 277                 /*
 278                  *      We have been given a non page aligned block of
 279                  *      the data we asked for + a bit. We have been given
 280                  *      the start pointer and we know the length.. 
 281                  */
 282 
 283                 if (length <= 0)
 284                         break;
 285                 /*
 286                  *      Copy the bytes
 287                  */
 288                 memcpy_tofs(buf+copied, start, length);
 289                 file->f_pos+=length;    /* Move down the file */
 290                 bytes-=length;
 291                 copied+=length;
 292                 if(length<thistime)
 293                         break;  /* End of file */
 294         }
 295         free_page((unsigned long) page);
 296         return copied;
 297 
 298 }

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