home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / fs / proc / net.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-12  |  11.3 KB  |  397 lines

  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.                struct dirent *, int);
  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. #ifdef CONFIG_NETROM
  81. extern int nr_get_info(char *, char **, off_t, int);
  82. extern int nr_nodes_get_info(char *, char **, off_t, int);
  83. extern int nr_neigh_get_info(char *, char **, off_t, int);
  84. #endif /* CONFIG_NETROM */
  85. #endif /* CONFIG_AX25 */
  86. #ifdef CONFIG_ATALK
  87. extern int atalk_get_info(char *, char **, off_t, int);
  88. extern int atalk_rt_get_info(char *, char **, off_t, int);
  89. extern int atalk_if_get_info(char *, char **, off_t, int);
  90. #endif
  91.  
  92.  
  93. static struct file_operations proc_net_operations = {
  94.     NULL,            /* lseek - default */
  95.     proc_readnet,        /* read - bad */
  96.     NULL,            /* write - bad */
  97.     proc_readnetdir,    /* readdir */
  98.     NULL,            /* select - default */
  99.     NULL,            /* ioctl - default */
  100.     NULL,            /* mmap */
  101.     NULL,            /* no special open code */
  102.     NULL,            /* no special release code */
  103.     NULL            /* can't fsync */
  104. };
  105.  
  106. /*
  107.  * proc directories can do almost nothing..
  108.  */
  109. struct inode_operations proc_net_inode_operations = {
  110.     &proc_net_operations,    /* default net directory file-ops */
  111.     NULL,            /* create */
  112.     proc_lookupnet,        /* lookup */
  113.     NULL,            /* link */
  114.     NULL,            /* unlink */
  115.     NULL,            /* symlink */
  116.     NULL,            /* mkdir */
  117.     NULL,            /* rmdir */
  118.     NULL,            /* mknod */
  119.     NULL,            /* rename */
  120.     NULL,            /* readlink */
  121.     NULL,            /* follow_link */
  122.     NULL,            /* bmap */
  123.     NULL,            /* truncate */
  124.     NULL            /* permission */
  125. };
  126.  
  127. static struct proc_dir_entry net_dir[] = {
  128.     { PROC_NET,        1, "." },
  129.     { PROC_ROOT_INO,    2, ".." },
  130.     { PROC_NET_UNIX,    4, "unix" },
  131. #ifdef CONFIG_INET
  132.     { PROC_NET_ARP,        3, "arp" },
  133.     { PROC_NET_ROUTE,    5, "route" },
  134.     { PROC_NET_DEV,        3, "dev" },
  135.     { PROC_NET_RAW,        3, "raw" },
  136.     { PROC_NET_TCP,        3, "tcp" },
  137.     { PROC_NET_UDP,        3, "udp" },
  138.     { PROC_NET_SNMP,    4, "snmp" },
  139.     { PROC_NET_SOCKSTAT,    8, "sockstat" },
  140. #ifdef CONFIG_INET_RARP
  141.     { PROC_NET_RARP,    4, "rarp"},
  142. #endif
  143. #ifdef CONFIG_IP_MULTICAST
  144.     { PROC_NET_IGMP,    4, "igmp"},
  145. #endif
  146. #ifdef CONFIG_IP_FIREWALL
  147.     { PROC_NET_IPFWFWD,    10, "ip_forward"},
  148.     { PROC_NET_IPFWBLK,    8,  "ip_block"},
  149. #endif
  150. #ifdef CONFIG_IP_MASQUERADE
  151.     { PROC_NET_IPMSQHST,    13, "ip_masquerade"},
  152. #endif
  153. #ifdef CONFIG_IP_ACCT
  154.     { PROC_NET_IPACCT,    7,  "ip_acct"},
  155. #endif
  156. #if    defined(CONFIG_WAVELAN)
  157.     { PROC_NET_WAVELAN,    7, "wavelan" },
  158. #endif    /* defined(CONFIG_WAVELAN) */
  159. #endif    /* CONFIG_INET */
  160. #ifdef CONFIG_IPX
  161.     { PROC_NET_IPX_ROUTE,    9, "ipx_route" },
  162.     { PROC_NET_IPX,        3, "ipx" },
  163.     { PROC_NET_IPX_INTERFACE, 13, "ipx_interface" },
  164. #endif /* CONFIG_IPX */
  165. #ifdef CONFIG_AX25
  166.     { PROC_NET_AX25_ROUTE,    10, "ax25_route" },
  167.     { PROC_NET_AX25,    4, "ax25" },
  168. #ifdef CONFIG_NETROM
  169.     { PROC_NET_NR_NODES,    8, "nr_nodes" },
  170.     { PROC_NET_NR_NEIGH,    8, "nr_neigh" },
  171.     { PROC_NET_NR,        2, "nr" },
  172. #endif /* CONFIG_NETROM */
  173. #endif /* CONFIG_AX25 */
  174. #ifdef CONFIG_ATALK
  175.     { PROC_NET_ATALK,    9, "appletalk" },
  176.     { PROC_NET_AT_ROUTE,    11,"atalk_route" },
  177.     { PROC_NET_ATIF,    11,"atalk_iface" },
  178. #endif /* CONFIG_ATALK */
  179.     { 0, 0, NULL }
  180. };
  181.  
  182. #define NR_NET_DIRENTRY ((sizeof (net_dir))/(sizeof (net_dir[0])) - 1)
  183.  
  184. static int proc_lookupnet(struct inode * dir,const char * name, int len,
  185.     struct inode ** result)
  186. {
  187.     struct proc_dir_entry *de;
  188.  
  189.     *result = NULL;
  190.     if (!dir)
  191.         return -ENOENT;
  192.     if (!S_ISDIR(dir->i_mode)) {
  193.         iput(dir);
  194.         return -ENOENT;
  195.     }
  196.     for (de = net_dir ; de->name ; de++) {
  197.         if (!proc_match(len, name, de))
  198.             continue;
  199.         *result = iget(dir->i_sb, de->low_ino);
  200.         iput(dir);
  201.         if (!*result)
  202.             return -ENOENT;
  203.         return 0;
  204.     }
  205.     iput(dir);
  206.     return -ENOENT;
  207. }
  208.  
  209. static int proc_readnetdir(struct inode * inode, struct file * filp,
  210.     struct dirent * dirent, int count)
  211. {
  212.     struct proc_dir_entry * de;
  213.     unsigned int ino;
  214.     int i,j;
  215.  
  216.     if (!inode || !S_ISDIR(inode->i_mode))
  217.         return -EBADF;
  218.     ino = inode->i_ino;
  219.     if (((unsigned) filp->f_pos) < NR_NET_DIRENTRY) {
  220.         de = net_dir + filp->f_pos;
  221.         filp->f_pos++;
  222.         i = de->namelen;
  223.         ino = de->low_ino;
  224.         put_fs_long(ino, &dirent->d_ino);
  225.         put_fs_word(i,&dirent->d_reclen);
  226.         put_fs_byte(0,i+dirent->d_name);
  227.         j = i;
  228.         while (i--)
  229.             put_fs_byte(de->name[i], i+dirent->d_name);
  230.         return j;
  231.     }
  232.     return 0;
  233. }
  234.  
  235.  
  236. #define PROC_BLOCK_SIZE    (3*1024)        /* 4K page size but our output routines use some slack for overruns */
  237.  
  238. static int proc_readnet(struct inode * inode, struct file * file,
  239.             char * buf, int count)
  240. {
  241.     char * page;
  242.     int length;
  243.     unsigned int ino;
  244.     int bytes=count;
  245.     int thistime;
  246.     int copied=0;
  247.     char *start;
  248.  
  249.     if (count < 0)
  250.         return -EINVAL;
  251.     if (!(page = (char*) __get_free_page(GFP_KERNEL)))
  252.         return -ENOMEM;
  253.     ino = inode->i_ino;
  254.  
  255.     while(bytes>0)
  256.     {
  257.         thistime=bytes;
  258.         if(bytes>PROC_BLOCK_SIZE)
  259.             thistime=PROC_BLOCK_SIZE;
  260.  
  261.         switch (ino) 
  262.         {
  263.             case PROC_NET_UNIX:
  264.                 length = unix_get_info(page,&start,file->f_pos,thistime);
  265.                 break;
  266. #ifdef CONFIG_INET
  267.             case PROC_NET_SOCKSTAT:
  268.                 length = afinet_get_info(page,&start,file->f_pos,thistime);
  269.                 break;
  270.             case PROC_NET_ARP:
  271.                 length = arp_get_info(page,&start,file->f_pos,thistime);
  272.                 break;
  273.             case PROC_NET_ROUTE:
  274.                 length = rt_get_info(page,&start,file->f_pos,thistime);
  275.                 break;
  276.             case PROC_NET_DEV:
  277.                 length = dev_get_info(page,&start,file->f_pos,thistime);
  278.                 break;
  279.             case PROC_NET_RAW:
  280.                 length = raw_get_info(page,&start,file->f_pos,thistime);
  281.                 break;
  282.             case PROC_NET_TCP:
  283.                 length = tcp_get_info(page,&start,file->f_pos,thistime);
  284.                 break;
  285.             case PROC_NET_UDP:
  286.                 length = udp_get_info(page,&start,file->f_pos,thistime);
  287.                 break;
  288.             case PROC_NET_SNMP:
  289.                 length = snmp_get_info(page, &start, file->f_pos,thistime);
  290.                 break;
  291. #ifdef CONFIG_IP_MULTICAST
  292.             case PROC_NET_IGMP:
  293.                 length = ip_mc_procinfo(page, &start, file->f_pos,thistime);
  294.                 break;
  295. #endif
  296. #ifdef CONFIG_IP_FIREWALL
  297.             case PROC_NET_IPFWFWD:
  298.                 length = ip_fw_fwd_procinfo(page, &start, file->f_pos,
  299.                     thistime, (file->f_flags & O_ACCMODE) == O_RDWR);
  300.                 break;
  301.             case PROC_NET_IPFWBLK:
  302.                 length = ip_fw_blk_procinfo(page, &start, file->f_pos,
  303.                     thistime, (file->f_flags & O_ACCMODE) == O_RDWR);
  304.                 break;
  305. #endif
  306. #ifdef CONFIG_IP_ACCT
  307.             case PROC_NET_IPACCT:
  308.                 length = ip_acct_procinfo(page, &start, file->f_pos,
  309.                     thistime, (file->f_flags & O_ACCMODE) == O_RDWR);
  310.                 break;
  311. #endif
  312. #ifdef CONFIG_IP_MASQUERADE
  313.             case PROC_NET_IPMSQHST:
  314.                 length = ip_msqhst_procinfo(page, &start, file->f_pos,thistime);
  315.                 break;
  316. #endif
  317. #ifdef CONFIG_INET_RARP                
  318.             case PROC_NET_RARP:
  319.                 length = rarp_get_info(page,&start,file->f_pos,thistime);
  320.                 break;
  321. #endif /* CONFIG_INET_RARP */                
  322. #if    defined(CONFIG_WAVELAN)
  323.             case PROC_NET_WAVELAN:
  324.                 length = wavelan_get_info(page, &start, file->f_pos, thistime);
  325.                 break;
  326. #endif    /* defined(CONFIG_WAVELAN) */
  327. #endif /* CONFIG_INET */
  328. #ifdef CONFIG_IPX
  329.             case PROC_NET_IPX_INTERFACE:
  330.                 length = ipx_get_interface_info(page, &start, file->f_pos, thistime);
  331.                 break;
  332.             case PROC_NET_IPX_ROUTE:
  333.                 length = ipx_rt_get_info(page,&start,file->f_pos,thistime);
  334.                 break;
  335.             case PROC_NET_IPX:
  336.                 length = ipx_get_info(page,&start,file->f_pos,thistime);
  337.                 break;
  338. #endif /* CONFIG_IPX */
  339. #ifdef CONFIG_ATALK
  340.             case PROC_NET_ATALK:
  341.                 length = atalk_get_info(page, &start, file->f_pos, thistime);
  342.                 break;
  343.             case PROC_NET_AT_ROUTE:
  344.                 length = atalk_rt_get_info(page, &start, file->f_pos, thistime);
  345.                 break;
  346.             case PROC_NET_ATIF:
  347.                 length = atalk_if_get_info(page, &start, file->f_pos, thistime);
  348.                 break;
  349. #endif /* CONFIG_ATALK */
  350. #ifdef CONFIG_AX25
  351.             case PROC_NET_AX25_ROUTE:
  352.                 length = ax25_rt_get_info(page,&start,file->f_pos,thistime);
  353.                 break;
  354.             case PROC_NET_AX25:
  355.                 length = ax25_get_info(page,&start,file->f_pos,thistime);
  356.                 break;
  357. #ifdef CONFIG_NETROM
  358.             case PROC_NET_NR_NODES:
  359.                 length = nr_nodes_get_info(page,&start,file->f_pos,thistime);
  360.                 break;
  361.             case PROC_NET_NR_NEIGH:
  362.                 length = nr_neigh_get_info(page,&start,file->f_pos,thistime);
  363.                 break;
  364.             case PROC_NET_NR:
  365.                 length = nr_get_info(page,&start,file->f_pos,thistime);
  366.                 break;
  367. #endif /* CONFIG_NETROM */
  368. #endif /* CONFIG_AX25 */
  369.  
  370.             default:
  371.                 free_page((unsigned long) page);
  372.                 return -EBADF;
  373.         }
  374.         
  375.         /*
  376.           *    We have been given a non page aligned block of
  377.          *    the data we asked for + a bit. We have been given
  378.           *    the start pointer and we know the length.. 
  379.          */
  380.  
  381.         if (length <= 0)
  382.             break;
  383.         /*
  384.           *    Copy the bytes
  385.          */
  386.         memcpy_tofs(buf+copied, start, length);
  387.         file->f_pos+=length;    /* Move down the file */
  388.         bytes-=length;
  389.         copied+=length;
  390.         if(length<thistime)
  391.             break;    /* End of file */
  392.     }
  393.     free_page((unsigned long) page);
  394.     return copied;
  395.  
  396. }
  397.