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 
  56 static struct file_operations proc_net_operations = {
  57         NULL,                   /* lseek - default */
  58         proc_readnet,           /* read - bad */
  59         NULL,                   /* write - bad */
  60         proc_readnetdir,        /* readdir */
  61         NULL,                   /* select - default */
  62         NULL,                   /* ioctl - default */
  63         NULL,                   /* mmap */
  64         NULL,                   /* no special open code */
  65         NULL,                   /* no special release code */
  66         NULL                    /* can't fsync */
  67 };
  68 
  69 /*
  70  * proc directories can do almost nothing..
  71  */
  72 struct inode_operations proc_net_inode_operations = {
  73         &proc_net_operations,   /* default net directory file-ops */
  74         NULL,                   /* create */
  75         proc_lookupnet,         /* lookup */
  76         NULL,                   /* link */
  77         NULL,                   /* unlink */
  78         NULL,                   /* symlink */
  79         NULL,                   /* mkdir */
  80         NULL,                   /* rmdir */
  81         NULL,                   /* mknod */
  82         NULL,                   /* rename */
  83         NULL,                   /* readlink */
  84         NULL,                   /* follow_link */
  85         NULL,                   /* bmap */
  86         NULL,                   /* truncate */
  87         NULL                    /* permission */
  88 };
  89 
  90 static struct proc_dir_entry net_dir[] = {
  91         { 1,2,".." },
  92         { 8,1,"." },
  93         { 128,4,"unix" }
  94 #ifdef CONFIG_INET
  95         ,{ 129,3,"arp" },
  96         { 130,5,"route" },
  97         { 131,3,"dev" },
  98         { 132,3,"raw" },
  99         { 133,3,"tcp" },
 100         { 134,3,"udp" },
 101 #ifdef CONFIG_INET_RARP
 102         { 135,4,"rarp"}
 103 #endif
 104 #endif  /* CONFIG_INET */
 105 #ifdef CONFIG_IPX
 106         ,{ 136,9,"ipx_route" },
 107         { 137,3,"ipx" }
 108 #endif /* CONFIG_IPX */
 109 };
 110 
 111 #define NR_NET_DIRENTRY ((sizeof (net_dir))/(sizeof (net_dir[0])))
 112 
 113 
 114 static int proc_lookupnet(struct inode * dir,const char * name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 115         struct inode ** result)
 116 {
 117         unsigned int ino;
 118         int i;
 119 
 120         *result = NULL;
 121         if (!dir)
 122                 return -ENOENT;
 123         if (!S_ISDIR(dir->i_mode)) {
 124                 iput(dir);
 125                 return -ENOENT;
 126         }
 127         i = NR_NET_DIRENTRY;
 128         while (i-- > 0 && !proc_match(len,name,net_dir+i))
 129                 /* nothing */;
 130         if (i < 0) {
 131                 iput(dir);
 132                 return -ENOENT;
 133         }
 134         ino = net_dir[i].low_ino;
 135         if (!(*result = iget(dir->i_sb,ino))) {
 136                 iput(dir);
 137                 return -ENOENT;
 138         }
 139         iput(dir);
 140         return 0;
 141 }
 142 
 143 static int proc_readnetdir(struct inode * inode, struct file * filp,
     /* [previous][next][first][last][top][bottom][index][help] */
 144         struct dirent * dirent, int count)
 145 {
 146         struct proc_dir_entry * de;
 147         unsigned int ino;
 148         int i,j;
 149 
 150         if (!inode || !S_ISDIR(inode->i_mode))
 151                 return -EBADF;
 152         ino = inode->i_ino;
 153         if (((unsigned) filp->f_pos) < NR_NET_DIRENTRY) {
 154                 de = net_dir + filp->f_pos;
 155                 filp->f_pos++;
 156                 i = de->namelen;
 157                 ino = de->low_ino;
 158                 put_fs_long(ino, &dirent->d_ino);
 159                 put_fs_word(i,&dirent->d_reclen);
 160                 put_fs_byte(0,i+dirent->d_name);
 161                 j = i;
 162                 while (i--)
 163                         put_fs_byte(de->name[i], i+dirent->d_name);
 164                 return j;
 165         }
 166         return 0;
 167 }
 168 
 169 
 170 #define PROC_BLOCK_SIZE (3*1024)                /* 4K page size but our output routines use some slack for overruns */
 171 
 172 static int proc_readnet(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 173                         char * buf, int count)
 174 {
 175         char * page;
 176         int length;
 177         unsigned int ino;
 178         int bytes=count;
 179         int thistime;
 180         int copied=0;
 181         char *start;
 182 
 183         if (count < 0)
 184                 return -EINVAL;
 185         if (!(page = (char*) __get_free_page(GFP_KERNEL)))
 186                 return -ENOMEM;
 187         ino = inode->i_ino;
 188 
 189         while(bytes>0)
 190         {
 191                 thistime=bytes;
 192                 if(bytes>PROC_BLOCK_SIZE)
 193                         thistime=PROC_BLOCK_SIZE;
 194 
 195                 switch (ino) 
 196                 {
 197                         case 128:
 198                                 length = unix_get_info(page,&start,file->f_pos,thistime);
 199                                 break;
 200 #ifdef CONFIG_INET
 201                         case 129:
 202                                 length = arp_get_info(page,&start,file->f_pos,thistime);
 203                                 break;
 204                         case 130:
 205                                 length = rt_get_info(page,&start,file->f_pos,thistime);
 206                                 break;
 207                         case 131:
 208                                 length = dev_get_info(page,&start,file->f_pos,thistime);
 209                                 break;
 210                         case 132:
 211                                 length = raw_get_info(page,&start,file->f_pos,thistime);
 212                                 break;
 213                         case 133:
 214                                 length = tcp_get_info(page,&start,file->f_pos,thistime);
 215                                 break;
 216                         case 134:
 217                                 length = udp_get_info(page,&start,file->f_pos,thistime);
 218                                 break;
 219                         case 135:
 220                                 length = rarp_get_info(page,&start,file->f_pos,thistime);
 221                                 break;
 222 #endif /* CONFIG_INET */
 223 #ifdef CONFIG_IPX
 224                         case 136:
 225                                 length = ipx_rt_get_info(page,&start,file->f_pos,thistime);
 226                                 break;
 227                         case 137:
 228                                 length = ipx_get_info(page,&start,file->f_pos,thistime);
 229                                 break;
 230 #endif /* CONFIG_IPX */
 231                         default:
 232                                 free_page((unsigned long) page);
 233                                 return -EBADF;
 234                 }
 235                 
 236                 /*
 237                  *      We have been given a non page aligned block of
 238                  *      the data we asked for + a bit. We have been given
 239                  *      the start pointer and we know the length.. 
 240                  */
 241 
 242                 /*
 243                  *      Copy the bytes
 244                  */
 245                 memcpy_tofs(buf+copied, start, length);
 246                 file->f_pos+=length;    /* Move down the file */
 247                 bytes-=length;
 248                 copied+=length;
 249                 if(length<thistime)
 250                         break;  /* End of file */
 251         }
 252         free_page((unsigned long) page);
 253         return copied;
 254 
 255 }

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