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

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