Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / net / tux / proc.c
1 /*
2  * TUX - Integrated Application Protocols Layer and Object Cache
3  *
4  * Copyright (C) 2000, 2001, Ingo Molnar <mingo@redhat.com>
5  *
6  * proc.c: /proc/sys/tux handling
7  */
8
9 #include <net/tux.h>
10
11 /****************************************************************
12  *      This program is free software; you can redistribute it and/or modify
13  *      it under the terms of the GNU General Public License as published by
14  *      the Free Software Foundation; either version 2, or (at your option)
15  *      any later version.
16  *
17  *      This program is distributed in the hope that it will be useful,
18  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *      GNU General Public License for more details.
21  *
22  *      You should have received a copy of the GNU General Public License
23  *      along with this program; if not, write to the Free Software
24  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  *
26  ****************************************************************/
27
28 char tux_common_docroot[200] = "/var/www/tux/";
29 char tux_http_subdocroot[200] = "";
30 char tux_ftp_subdocroot[200] = "";
31 char tux_logfile[200] = "/var/log/tux";
32 char tux_cgiroot[200] = "/var/www/tux/cgiroot/";
33 char tux_404_page[200] = "404.html";
34 char tux_default_vhost[200] = "default";
35 char tux_extra_html_header[600];
36 unsigned int tux_extra_html_header_size = 0;
37
38 int tux_cgi_uid = -1;
39 int tux_cgi_gid = -1;
40 unsigned int tux_clientport = 8080;
41 unsigned int tux_logging = 0;
42 unsigned int tux_threads = 2;
43 unsigned int tux_max_connect = 10000;
44 unsigned int tux_max_keepalives = 10000;
45 unsigned int tux_max_backlog = 2048;
46 unsigned int tux_keepalive_timeout = 0;
47 unsigned int tux_max_output_bandwidth = 0;
48 unsigned int tux_defer_accept = 1;
49 unsigned int tux_mode_forbidden = 0 /*S_IXUGO*/; /* do not allow executable (CGI) files */
50 unsigned int tux_mode_allowed = S_IROTH; /* allow access if read-other is set */
51 unsigned int tux_virtual_server = 0;
52 unsigned int tux_ftp_virtual_server = 0;
53 unsigned int mass_hosting_hash = 0;
54 unsigned int strip_host_tail = 0;
55 unsigned int tux_max_object_size = 0;
56 cpumask_t tux_log_cpu_mask = CPU_MASK_ALL;
57 unsigned int tux_compression = 0;
58 unsigned int tux_noid = 0;
59 unsigned int tux_cgi_inherit_cpu = 0;
60 cpumask_t tux_cgi_cpu_mask = CPU_MASK_ALL;
61 unsigned int tux_zerocopy_header = 1;
62 unsigned int tux_max_free_requests = 1000;
63 unsigned int tux_ignore_query = 0;
64 unsigned int tux_all_userspace = 0;
65 unsigned int tux_redirect_logging = 1;
66 unsigned int tux_max_header_len = 3000;
67 unsigned int tux_referer_logging = 0;
68 unsigned int tux_generate_etags = 1;
69 unsigned int tux_generate_last_mod = 1;
70 unsigned int tux_generate_cache_control = 1;
71 unsigned int tux_ip_logging = 1;
72 unsigned int tux_ftp_wait_close = 1;
73 unsigned int tux_ftp_log_retr_only = 0;
74 unsigned int tux_hide_unreadable = 1;
75 unsigned int tux_http_dir_indexing = 0;
76 unsigned int tux_log_incomplete = 0;
77 unsigned int tux_cpu_offset = 0;
78 unsigned int tux_ftp_login_message = 0;
79
80 static struct ctl_table_header *tux_table_header;
81
82 static ctl_table tux_table[] = {
83         {       NET_TUX_DOCROOT,
84                 "documentroot",
85                 &tux_common_docroot,
86                 sizeof(tux_common_docroot),
87                 0644,
88                 NULL,
89                 proc_dostring,
90                 &sysctl_string,
91                 NULL,
92                 NULL,
93                 NULL
94         },
95         {       NET_TUX_DOCROOT,
96                 "http_subdocroot",
97                 &tux_http_subdocroot,
98                 sizeof(tux_http_subdocroot),
99                 0644,
100                 NULL,
101                 proc_dostring,
102                 &sysctl_string,
103                 NULL,
104                 NULL,
105                 NULL
106         },
107         {       NET_TUX_DOCROOT,
108                 "ftp_subdocroot",
109                 &tux_ftp_subdocroot,
110                 sizeof(tux_ftp_subdocroot),
111                 0644,
112                 NULL,
113                 proc_dostring,
114                 &sysctl_string,
115                 NULL,
116                 NULL,
117                 NULL
118         },
119         {       NET_TUX_LOGFILE,
120                 "logfile",
121                 &tux_logfile,
122                 sizeof(tux_logfile),
123                 0644,
124                 NULL,
125                 proc_dostring,
126                 &sysctl_string,
127                 NULL,
128                 NULL,
129                 NULL
130         },
131         {       NET_TUX_THREADS,
132                 "threads",
133                 &tux_threads,
134                 sizeof(int),
135                 0644,
136                 NULL,
137                 proc_dointvec,
138                 &sysctl_intvec,
139                 NULL,
140                 NULL,
141                 NULL
142         },
143         {       NET_TUX_KEEPALIVE_TIMEOUT,
144                 "keepalive_timeout",
145                 &tux_keepalive_timeout,
146                 sizeof(int),
147                 0644,
148                 NULL,
149                 proc_dointvec,
150                 &sysctl_intvec,
151                 NULL,
152                 NULL,
153                 NULL
154         },
155         {       NET_TUX_MAX_KEEPALIVE_BW,
156                 "max_output_bandwidth",
157                 &tux_max_output_bandwidth,
158                 sizeof(int),
159                 0644,
160                 NULL,
161                 proc_dointvec,
162                 &sysctl_intvec,
163                 NULL,
164                 NULL,
165                 NULL
166         },
167         {       NET_TUX_DEFER_ACCEPT,
168                 "defer_accept",
169                 &tux_defer_accept,
170                 sizeof(int),
171                 0644,
172                 NULL,
173                 proc_dointvec,
174                 &sysctl_intvec,
175                 NULL,
176                 NULL,
177                 NULL
178         },
179         {       NET_TUX_MAX_BACKLOG,
180                 "max_backlog",
181                 &tux_max_backlog,
182                 sizeof(int),
183                 0644,
184                 NULL,
185                 proc_dointvec,
186                 &sysctl_intvec,
187                 NULL,
188                 NULL,
189                 NULL
190         },
191         {       NET_TUX_MAX_CONNECT,
192                 "max_connect",
193                 &tux_max_connect,
194                 sizeof(int),
195                 0644,
196                 NULL,
197                 proc_dointvec,
198                 &sysctl_intvec,
199                 NULL,
200                 NULL,
201                 NULL
202         },
203         {       NET_TUX_MAX_KEEPALIVES,
204                 "max_keepalives",
205                 &tux_max_keepalives,
206                 sizeof(int),
207                 0644,
208                 NULL,
209                 proc_dointvec,
210                 &sysctl_intvec,
211                 NULL,
212                 NULL,
213                 NULL
214         },
215         {       NET_TUX_MODE_FORBIDDEN,
216                 "mode_forbidden",
217                 &tux_mode_forbidden,
218                 sizeof(int),
219                 0644,
220                 NULL,
221                 proc_dointvec,
222                 &sysctl_intvec,
223                 NULL,
224                 NULL,
225                 NULL
226         },
227         {       NET_TUX_MODE_ALLOWED,
228                 "mode_allowed",
229                 &tux_mode_allowed,
230                 sizeof(int),
231                 0644,
232                 NULL,
233                 proc_dointvec,
234                 &sysctl_intvec,
235                 NULL,
236                 NULL,
237                 NULL
238         },
239         {       NET_TUX_CGI_UID,
240                 "cgi_uid",
241                 &tux_cgi_uid,
242                 sizeof(int),
243                 0644,
244                 NULL,
245                 proc_dointvec,
246                 &sysctl_intvec,
247                 NULL,
248                 NULL,
249                 NULL
250         },
251         {       NET_TUX_CGI_GID,
252                 "cgi_gid",
253                 &tux_cgi_gid,
254                 sizeof(int),
255                 0644,
256                 NULL,
257                 proc_dointvec,
258                 &sysctl_intvec,
259                 NULL,
260                 NULL,
261                 NULL
262         },
263         {       NET_TUX_CGIROOT,
264                 "cgiroot",
265                 &tux_cgiroot,
266                 sizeof(tux_cgiroot),
267                 0644,
268                 NULL,
269                 proc_dostring,
270                 &sysctl_string,
271                 NULL,
272                 NULL,
273                 NULL
274         },
275         {       NET_TUX_404_PAGE,
276                 "404_page",
277                 &tux_404_page,
278                 sizeof(tux_404_page),
279                 0644,
280                 NULL,
281                 proc_dostring,
282                 &sysctl_string,
283                 NULL,
284                 NULL,
285                 NULL
286         },
287         {       NET_TUX_404_PAGE,
288                 "default_vhost",
289                 &tux_default_vhost,
290                 sizeof(tux_default_vhost),
291                 0644,
292                 NULL,
293                 proc_dostring,
294                 &sysctl_string,
295                 NULL,
296                 NULL,
297                 NULL
298         },
299         {       NET_TUX_404_PAGE,
300                 "extra_html_header",
301                 &tux_extra_html_header,
302                 sizeof(tux_extra_html_header),
303                 0644,
304                 NULL,
305                 proc_dostring,
306                 &sysctl_string,
307                 NULL,
308                 NULL,
309                 NULL
310         },
311         {       NET_TUX_CLIENTPORT,
312                 "extra_html_header_size",
313                 &tux_extra_html_header_size,
314                 sizeof(int),
315                 0644,
316                 NULL,
317                 proc_dointvec,
318                 &sysctl_intvec,
319                 NULL,
320                 NULL,
321                 NULL
322         },
323         {       NET_TUX_CLIENTPORT,
324                 "clientport",
325                 &tux_clientport,
326                 sizeof(int),
327                 0644,
328                 NULL,
329                 proc_dointvec,
330                 &sysctl_intvec,
331                 NULL,
332                 NULL,
333                 NULL
334         },
335         {       NET_TUX_CLIENTPORT,
336                 "generate_etags",
337                 &tux_generate_etags,
338                 sizeof(int),
339                 0644,
340                 NULL,
341                 proc_dointvec,
342                 &sysctl_intvec,
343                 NULL,
344                 NULL,
345                 NULL
346         },
347         {       NET_TUX_CLIENTPORT,
348                 "generate_last_mod",
349                 &tux_generate_last_mod,
350                 sizeof(int),
351                 0644,
352                 NULL,
353                 proc_dointvec,
354                 &sysctl_intvec,
355                 NULL,
356                 NULL,
357                 NULL
358         },
359         {       NET_TUX_CLIENTPORT,
360                 "generate_cache_control",
361                 &tux_generate_cache_control,
362                 sizeof(int),
363                 0644,
364                 NULL,
365                 proc_dointvec,
366                 &sysctl_intvec,
367                 NULL,
368                 NULL,
369                 NULL
370         },
371         {       NET_TUX_CLIENTPORT,
372                 "ip_logging",
373                 &tux_ip_logging,
374                 sizeof(int),
375                 0644,
376                 NULL,
377                 proc_dointvec,
378                 &sysctl_intvec,
379                 NULL,
380                 NULL,
381                 NULL
382         },
383         {       NET_TUX_CLIENTPORT,
384                 "ftp_wait_close",
385                 &tux_ftp_wait_close,
386                 sizeof(int),
387                 0644,
388                 NULL,
389                 proc_dointvec,
390                 &sysctl_intvec,
391                 NULL,
392                 NULL,
393                 NULL
394         },
395         {       NET_TUX_CLIENTPORT,
396                 "ftp_log_retr_only",
397                 &tux_ftp_log_retr_only,
398                 sizeof(int),
399                 0644,
400                 NULL,
401                 proc_dointvec,
402                 &sysctl_intvec,
403                 NULL,
404                 NULL,
405                 NULL
406         },
407         {       NET_TUX_CLIENTPORT,
408                 "http_dir_indexing",
409                 &tux_http_dir_indexing,
410                 sizeof(int),
411                 0644,
412                 NULL,
413                 proc_dointvec,
414                 &sysctl_intvec,
415                 NULL,
416                 NULL,
417                 NULL
418         },
419         {       NET_TUX_CLIENTPORT,
420                 "hide_unreadable",
421                 &tux_hide_unreadable,
422                 sizeof(int),
423                 0644,
424                 NULL,
425                 proc_dointvec,
426                 &sysctl_intvec,
427                 NULL,
428                 NULL,
429                 NULL
430         },
431         {       NET_TUX_CLIENTPORT,
432                 "log_incomplete",
433                 &tux_log_incomplete,
434                 sizeof(int),
435                 0644,
436                 NULL,
437                 proc_dointvec,
438                 &sysctl_intvec,
439                 NULL,
440                 NULL,
441                 NULL
442         },
443         {       NET_TUX_LOGGING,
444                 "TDprintk",
445                 &tux_TDprintk,
446                 sizeof(int),
447                 0644,
448                 NULL,
449                 proc_dointvec,
450                 &sysctl_intvec,
451                 NULL,
452                 NULL,
453                 NULL
454         },
455         {       NET_TUX_LOGGING,
456                 "Dprintk",
457                 &tux_Dprintk,
458                 sizeof(int),
459                 0644,
460                 NULL,
461                 proc_dointvec,
462                 &sysctl_intvec,
463                 NULL,
464                 NULL,
465                 NULL
466         },
467 #ifdef TUX_DPRINTK
468 #endif
469         {       NET_TUX_LOGGING,
470                 "logging",
471                 &tux_logging,
472                 sizeof(int),
473                 0644,
474                 NULL,
475                 proc_dointvec,
476                 &sysctl_intvec,
477                 NULL,
478                 NULL,
479                 NULL
480         },
481         {       NET_TUX_LOGENTRY_ALIGN_ORDER,
482                 "logentry_align_order",
483                 &tux_logentry_align_order,
484                 sizeof(int),
485                 0644,
486                 NULL,
487                 proc_dointvec,
488                 &sysctl_intvec,
489                 NULL,
490                 NULL,
491                 NULL
492         },
493         {       NET_TUX_ACK_PINGPONG,
494                 "ack_pingpong",
495                 &tux_ack_pingpong,
496                 sizeof(int),
497                 0644,
498                 NULL,
499                 proc_dointvec,
500                 &sysctl_intvec,
501                 NULL,
502                 NULL,
503                 NULL
504         },
505         {       NET_TUX_PUSH_ALL,
506                 "push_all",
507                 &tux_push_all,
508                 sizeof(int),
509                 0644,
510                 NULL,
511                 proc_dointvec,
512                 &sysctl_intvec,
513                 NULL,
514                 NULL,
515                 NULL
516         },
517         {       NET_TUX_ZEROCOPY_PARSE,
518                 "zerocopy_parse",
519                 &tux_zerocopy_parse,
520                 sizeof(int),
521                 0644,
522                 NULL,
523                 proc_dointvec,
524                 &sysctl_intvec,
525                 NULL,
526                 NULL,
527                 NULL
528         },
529         {       NET_TUX_VIRTUAL_SERVER,
530                 "virtual_server",
531                 &tux_virtual_server,
532                 sizeof(int),
533                 0644,
534                 NULL,
535                 proc_dointvec,
536                 &sysctl_intvec,
537                 NULL,
538                 NULL,
539                 NULL
540         },
541         {       NET_TUX_VIRTUAL_SERVER,
542                 "mass_hosting_hash",
543                 &mass_hosting_hash,
544                 sizeof(int),
545                 0644,
546                 NULL,
547                 proc_dointvec,
548                 &sysctl_intvec,
549                 NULL,
550                 NULL,
551                 NULL
552         },
553         {       NET_TUX_VIRTUAL_SERVER,
554                 "strip_host_tail",
555                 &strip_host_tail,
556                 sizeof(int),
557                 0644,
558                 NULL,
559                 proc_dointvec,
560                 &sysctl_intvec,
561                 NULL,
562                 NULL,
563                 NULL
564         },
565         {       NET_TUX_VIRTUAL_SERVER,
566                 "ftp_virtual_server",
567                 &tux_ftp_virtual_server,
568                 sizeof(int),
569                 0644,
570                 NULL,
571                 proc_dointvec,
572                 &sysctl_intvec,
573                 NULL,
574                 NULL,
575                 NULL
576         },
577         {       NET_TUX_MAX_OBJECT_SIZE,
578                 "max_object_size",
579                 &tux_max_object_size,
580                 sizeof(int),
581                 0644,
582                 NULL,
583                 proc_dointvec,
584                 &sysctl_intvec,
585                 NULL,
586                 NULL,
587                 NULL
588         },
589         {       NET_TUX_COMPRESSION,
590                 "compression",
591                 &tux_compression,
592                 sizeof(int),
593                 0644,
594                 NULL,
595                 proc_dointvec,
596                 &sysctl_intvec,
597                 NULL,
598                 NULL,
599                 NULL
600         },
601         {       NET_TUX_NOID,
602                 "noid",
603                 &tux_noid,
604                 sizeof(int),
605                 0644,
606                 NULL,
607                 proc_dointvec,
608                 &sysctl_intvec,
609                 NULL,
610                 NULL,
611                 NULL
612         },
613         {       NET_TUX_CGI_INHERIT_CPU,
614                 "cgi_inherit_cpu",
615                 &tux_cgi_inherit_cpu,
616                 sizeof(int),
617                 0644,
618                 NULL,
619                 proc_dointvec,
620                 &sysctl_intvec,
621                 NULL,
622                 NULL,
623                 NULL
624         },
625         {       NET_TUX_ZEROCOPY_HEADER,
626                 "zerocopy_header",
627                 &tux_zerocopy_header,
628                 sizeof(int),
629                 0644,
630                 NULL,
631                 proc_dointvec,
632                 &sysctl_intvec,
633                 NULL,
634                 NULL,
635                 NULL
636         },
637         {       NET_TUX_ZEROCOPY_SENDFILE,
638                 "zerocopy_sendfile",
639                 &tux_zerocopy_sendfile,
640                 sizeof(int),
641                 0644,
642                 NULL,
643                 proc_dointvec,
644                 &sysctl_intvec,
645                 NULL,
646                 NULL,
647                 NULL
648         },
649         {       NET_TUX_MAX_FREE_REQUESTS,
650                 "max_free_requests",
651                 &tux_max_free_requests,
652                 sizeof(int),
653                 0644,
654                 NULL,
655                 proc_dointvec,
656                 &sysctl_intvec,
657                 NULL,
658                 NULL,
659                 NULL
660         },
661         {       NET_TUX_ALL_USERSPACE,
662                 "all_userspace",
663                 &tux_all_userspace,
664                 sizeof(int),
665                 0644,
666                 NULL,
667                 proc_dointvec,
668                 &sysctl_intvec,
669                 NULL,
670                 NULL,
671                 NULL
672         },
673         {       NET_TUX_REDIRECT_LOGGING,
674                 "redirect_logging",
675                 &tux_redirect_logging,
676                 sizeof(int),
677                 0644,
678                 NULL,
679                 proc_dointvec,
680                 &sysctl_intvec,
681                 NULL,
682                 NULL,
683                 NULL
684         },
685         {       NET_TUX_IGNORE_QUERY,
686                 "ignore_query",
687                 &tux_ignore_query,
688                 sizeof(int),
689                 0644,
690                 NULL,
691                 proc_dointvec,
692                 &sysctl_intvec,
693                 NULL,
694                 NULL,
695                 NULL
696         },
697         {       NET_TUX_REFERER_LOGGING,
698                 "referer_logging",
699                 &tux_referer_logging,
700                 sizeof(int),
701                 0644,
702                 NULL,
703                 proc_dointvec,
704                 &sysctl_intvec,
705                 NULL,
706                 NULL,
707                 NULL
708         },
709         {       NET_TUX_REFERER_LOGGING,
710                 "cpu_offset",
711                 &tux_cpu_offset,
712                 sizeof(int),
713                 0644,
714                 NULL,
715                 proc_dointvec,
716                 &sysctl_intvec,
717                 NULL,
718                 NULL,
719                 NULL
720         },
721         {       NET_TUX_REFERER_LOGGING,
722                 "ftp_login_message",
723                 &tux_ftp_login_message,
724                 sizeof(int),
725                 0644,
726                 NULL,
727                 proc_dointvec,
728                 &sysctl_intvec,
729                 NULL,
730                 NULL,
731                 NULL
732         },
733         {       NET_TUX_MAX_HEADER_LEN,
734                 "max_header_len",
735                 &tux_max_header_len,
736                 sizeof(int),
737                 0644,
738                 NULL,
739                 proc_dointvec,
740                 &sysctl_intvec,
741                 NULL,
742                 NULL,
743                 NULL
744         },
745         {0, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL} };
746
747
748 static ctl_table tux_dir_table[] = {
749         {NET_TUX, "tux", NULL, 0, 0555, tux_table, NULL, NULL, NULL, NULL, NULL},
750         {0, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL}
751 };
752
753 static ctl_table tux_root_table[] = {
754         {CTL_NET, "net", NULL, 0, 0555, tux_dir_table, NULL, NULL, NULL, NULL, NULL},
755         {0, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL}
756 };
757
758
759 static struct proc_dir_entry * root_tux_dir;
760 static struct proc_dir_entry * log_cpu_mask_entry;
761 static struct proc_dir_entry * cgi_cpu_mask_entry;
762 static struct proc_dir_entry * stat_entry;
763 static struct proc_dir_entry * tux_dir [CONFIG_TUX_NUMTHREADS];
764 static struct proc_dir_entry * listen_dir [CONFIG_TUX_NUMTHREADS];
765
766 tux_socket_t tux_listen [CONFIG_TUX_NUMTHREADS][CONFIG_TUX_NUMSOCKETS] =
767  { [0 ... CONFIG_TUX_NUMTHREADS-1] = { {&tux_proto_http, 0, 80, NULL}, } };
768
769 static int cpu_mask_read_proc (char *page, char **start, off_t off,
770                                         int count, int *eof, void *data)
771 {
772         int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
773         if (count - len < 2)
774                 return -EINVAL;
775         len += sprintf(page + len, "\n");
776         return len;
777 }
778
779 static int cpu_mask_write_proc (struct file *file,
780                                         const char __user *buffer,
781                                         unsigned long count, void *data)
782 {
783         cpumask_t *mask = (cpumask_t *)data;
784         unsigned long full_count = count, err;
785         cpumask_t new_value;
786
787         err = cpumask_parse(buffer, count, new_value);
788         if (err)
789                 return err;
790
791         *mask = new_value;
792         return full_count;
793 }
794
795 #define LINE_SIZE 1024
796 #define LINE_MASK (LINE_SIZE-1)
797
798 static int print_request_stats (threadinfo_t *ti, char *page, unsigned int skip_count, unsigned int max_count)
799 {
800         struct list_head *head, *curr;
801         tux_req_t *req;
802         unsigned int count = 0, size, line_off, len;
803         char stat_line [LINE_SIZE];
804
805         if (!max_count)
806                 BUG();
807
808         head = &ti->all_requests;
809         curr = head->next;
810
811         while (curr != head) {
812                 req = list_entry(curr, tux_req_t, all);
813                 curr = curr->next;
814                 count++;
815                 if (count <= skip_count)
816                         continue;
817                 line_off = 0;
818 #define SP(x...) \
819         line_off += sprintf(stat_line + line_off, x)
820
821                 if (req->proto == &tux_proto_http)
822                         SP("0 ");
823                 else
824                         SP("1 ");
825
826                 SP("%p ", req);
827                 SP("%d ", req->atom_idx);
828                 if (req->atom_idx >= 1)
829                         SP("%p ", req->atoms[0]);
830                 else
831                         SP("........ ");
832                 if (req->atom_idx >= 2)
833                         SP("%p ", req->atoms[1]);
834                 else
835                         SP("........ ");
836                 if (!list_empty(&req->work))    SP("W");        else SP(".");
837                 if (!list_empty(&req->free))    SP("F");        else SP(".");
838                 if (!list_empty(&req->lru))     SP("L");        else SP(".");
839                 if (req->keep_alive)            SP("K");        else SP(".");
840                 if (req->idle_input)            SP("I");        else SP(".");
841                 if (timer_pending(&req->keepalive_timer))
842                                                 SP("T(%lu/%lu)",jiffies,req->keepalive_timer.expires);  else SP(".");
843                 if (req->wait_output_space)     SP("O");        else SP(".");
844                 if (timer_pending(&req->output_timer))
845                                                 SP("T");        else SP(".");
846                 SP(" %d ", req->error);
847                 SP(" %d ", req->status);
848
849 #define SP_HOST(ip,port) \
850                 SP("%d.%d.%d.%d:%d ",NIPQUAD(ip),port)
851
852                 if (req->sock) {
853                         if (req->sock->sk)
854                                 SP("%d:", req->sock->sk->sk_state);
855                         else
856                                 SP("-2:");
857                 } else
858                         SP("-1:");
859                 SP_HOST(req->client_addr, req->client_port);
860
861                 SP("%Ld ", req->total_file_len);
862                 SP("%Ld ", req->in_file ? req->in_file->f_pos : -1);
863                 if (req->proto == &tux_proto_http) {
864                         SP("%d ", req->method);
865                         SP("%d ", req->version);
866                 }
867                 if (req->proto == &tux_proto_ftp) {
868                         SP("%d ", req->ftp_command);
869                         if (req->data_sock) {
870                                 if (req->data_sock->sk)
871                                         SP("%d:",req->data_sock->sk->sk_state);
872                                 else
873                                         SP("-2:");
874                                 if (req->data_sock->sk)
875                                         SP_HOST(inet_sk(req->data_sock->sk)->daddr,
876                                                 inet_sk(req->data_sock->sk)->dport);
877                                 else
878                                         SP("-1:-1 ");
879                         } else
880                                 SP("-1 ");
881                 }
882                 SP("%p/%p %p/%p ", req->sock, req->sock ? req->sock->sk : (void *)-1, req->data_sock, req->data_sock ? req->data_sock->sk : (void *)-1);
883
884                 SP("%d\n", req->parsed_len);
885                 len = req->headers_len;
886                 if (len > 500)
887                         len = 500;
888                 SP("\n%d\n", len);
889                 memcpy(stat_line + line_off, req->headers, len);
890                 line_off += len;
891                 len = req->objectname_len;
892                 if (len > 100)
893                         len = 100;
894                 SP("\n%d\n", len);
895                 memcpy(stat_line + line_off, req->objectname, len);
896                 line_off += len;
897                 SP("\n\n<END>");
898                 if (line_off >= LINE_SIZE)
899                         BUG();
900                 Dprintk("printing req %p, count %d, page %p: {%s}.\n", req, count, page, stat_line);
901                 size = sprintf(page, "%-*s\n", LINE_SIZE-1, stat_line);
902                 if (size != LINE_SIZE)
903                         BUG();
904                 page += LINE_SIZE;
905                 if (count-skip_count >= max_count)
906                         break;
907         }
908
909         Dprintk("count: %d.\n", count-skip_count);
910         return count - skip_count;
911 }
912
913 static int stat_read_proc (char *page, char **start, off_t off,
914                         int max_size, int *eof, void *data)
915 {
916         unsigned int i, nr_total = 0, nr, nr_off, nr_skip, size = 0, nr_wanted;
917
918         Dprintk("START, page: %p, max_size: %d, off: %ld.\n", page, max_size, off);
919         *eof = 1;
920         if (max_size & LINE_MASK)
921                 return 0;
922         if (off & LINE_MASK)
923                 return 0;
924         if (!max_size)
925                 return 0;
926
927         nr_off = off/LINE_SIZE;
928
929         for (i = 0; i < nr_tux_threads; i++) {
930                 threadinfo_t *ti = threadinfo + i;
931                 spin_lock_irq(&ti->work_lock);
932                 nr = ti->nr_requests;
933                 Dprintk("ti: %p, nr: %d, nr_total: %d, nr_off: %d.\n", ti, nr, nr_total, nr_off);
934                 nr_total += nr;
935                 if (nr_off >= nr_total) {
936                         spin_unlock_irq(&ti->work_lock);
937                         continue;
938                 }
939                 nr_skip = nr_off - (nr_total - nr);
940                 nr_wanted = (max_size-size) / LINE_SIZE;
941                 Dprintk("nr_skip: %d, nr_wanted: %d.\n", nr_skip, nr_wanted);
942                 nr = print_request_stats(ti, page + size, nr_skip, nr_wanted);
943                 spin_unlock_irq(&ti->work_lock);
944                 nr_off += nr;
945                 size += nr * LINE_SIZE;
946                 Dprintk("ret: %d requests, size: %d.\n", nr, size);
947                 if (size > max_size)
948                         BUG();
949                 if (size == max_size)
950                         break;
951         }
952         Dprintk("DONE: size: %d.\n", size);
953
954         *start = page;
955
956         if (size)
957                 *eof = 0;
958         return size;
959 }
960
961 static int stat_write_proc (struct file *file, const char *buffer,
962                                         unsigned long count, void *data)
963 {
964         return -EINVAL;
965 }
966
967 #define MAX_STRING "http://255.255.255.255:65535"
968 #define MAX_STRINGLEN (sizeof(MAX_STRING))
969
970 #define INACTIVE_1 "[inactive]\n"
971 #define INACTIVE_2 "0\n"
972
973 static int listen_read_proc (char *page, char **start, off_t off,
974                         int count, int *eof, void *data)
975 {
976         tux_socket_t *listen = data;
977
978         if (count < MAX_STRINGLEN)
979                 return -EINVAL;
980
981         if (!listen->proto)
982                 return sprintf(page, INACTIVE_1);
983
984         return sprintf (page, "%s://%u.%u.%u.%u:%hu\n", listen->proto->name,
985                         HIPQUAD(listen->ip), listen->port);
986 }
987
988 static int listen_write_proc (struct file *file, const char *buffer,
989                                         unsigned long count, void *data)
990 {
991         char string [MAX_STRINGLEN];
992         unsigned int d1, d2, d3, d4;
993         unsigned short port;
994         tux_socket_t *listen = data;
995
996         if (!count)
997                 return -EINVAL;
998         if (count > MAX_STRINGLEN)
999                 count = MAX_STRINGLEN;
1000         if (copy_from_user(string, buffer, count))
1001                 return -EFAULT;
1002         string[count] = 0;
1003
1004         if (!strcmp(string, INACTIVE_1) || !strcmp(string, INACTIVE_2)) {
1005                 listen->proto = NULL;
1006                 listen->ip = 0;
1007                 listen->port = 0;
1008                 return count;
1009         }
1010
1011 #define MK_IP(a,b,c,d) ((a << 24) | (b << 16) | (c << 8) | d)
1012
1013         if (sscanf(string, "http://%u.%u.%u.%u:%hu\n",
1014                                         &d1, &d2, &d3, &d4, &port) == 5) {
1015                 listen->ip = MK_IP(d1,d2,d3,d4);
1016                 listen->port = port;
1017                 listen->proto = &tux_proto_http;
1018                 return count;
1019         }
1020
1021         if (sscanf(string, "ftp://%u.%u.%u.%u:%hu\n",
1022                                         &d1, &d2, &d3, &d4, &port) == 5) {
1023                 listen->ip = MK_IP(d1,d2,d3,d4);
1024                 listen->port = port;
1025                 listen->proto = &tux_proto_ftp;
1026                 return count;
1027         }
1028         printk(KERN_ERR "tux: invalid listen-socket parameters: %s\n", string);
1029         return -EINVAL;
1030 }
1031
1032 #define MAX_NAMELEN 10
1033
1034 static void register_tux_proc (unsigned int nr)
1035 {
1036         struct proc_dir_entry *entry;
1037         char name [MAX_NAMELEN];
1038         int i;
1039
1040         if (!root_tux_dir)
1041                 TUX_BUG();
1042
1043         sprintf(name, "%d", nr);
1044
1045         /* create /proc/net/tux/1234/ */
1046         tux_dir[nr] = proc_mkdir(name, root_tux_dir);
1047
1048         /* create /proc/net/tux/1234/listen/ */
1049         listen_dir[nr] = proc_mkdir("listen", tux_dir[nr]);
1050
1051         /* create /proc/net/tux/1234/listen/ */
1052         for (i = 0; i < CONFIG_TUX_NUMSOCKETS; i++) {
1053                 sprintf(name, "%d", i);
1054                 entry = create_proc_entry(name, 0700, listen_dir[nr]);
1055
1056                 entry->nlink = 1;
1057                 entry->data = (void *)(tux_listen[nr] + i);
1058                 entry->read_proc = listen_read_proc;
1059                 entry->write_proc = listen_write_proc;
1060                 tux_listen[nr][i].entry = entry;
1061         }
1062 }
1063
1064 static void unregister_tux_proc (unsigned int nr)
1065 {
1066         int i;
1067
1068         for (i = 0; i < CONFIG_TUX_NUMSOCKETS; i++) {
1069                 remove_proc_entry(tux_listen[nr][i].entry->name,listen_dir[nr]);
1070                 tux_listen[nr][i].entry = NULL;
1071         }
1072
1073         remove_proc_entry(listen_dir[nr]->name, tux_dir[nr]);
1074
1075         remove_proc_entry(tux_dir[nr]->name, root_tux_dir);
1076 }
1077
1078 static void cleanup_tux_proc (void)
1079 {
1080         int i;
1081
1082         Dprintk("cleaning up /proc/net/tux/\n");
1083
1084         for (i = 0; i < CONFIG_TUX_NUMTHREADS; i++)
1085                 unregister_tux_proc(i);
1086         remove_proc_entry(stat_entry->name, root_tux_dir);
1087         remove_proc_entry(log_cpu_mask_entry->name, root_tux_dir);
1088         remove_proc_entry(cgi_cpu_mask_entry->name, root_tux_dir);
1089         remove_proc_entry(root_tux_dir->name, proc_net);
1090 }
1091
1092 static void init_tux_proc (void)
1093 {
1094         struct proc_dir_entry *entry;
1095         int i;
1096
1097         if (root_tux_dir)
1098                 return;
1099
1100         /* create /proc/net/tux */
1101         root_tux_dir = proc_mkdir("tux", proc_net);
1102
1103         entry = create_proc_entry("log_cpu_mask", 0700, root_tux_dir);
1104
1105         entry->nlink = 1;
1106         entry->data = (void *)&tux_log_cpu_mask;
1107         entry->read_proc = cpu_mask_read_proc;
1108         entry->write_proc = cpu_mask_write_proc;
1109
1110         log_cpu_mask_entry = entry;
1111
1112         entry = create_proc_entry("cgi_cpu_mask", 0700, root_tux_dir);
1113
1114         entry->nlink = 1;
1115         entry->data = (void *)&tux_cgi_cpu_mask;
1116         entry->read_proc = cpu_mask_read_proc;
1117         entry->write_proc = cpu_mask_write_proc;
1118
1119         cgi_cpu_mask_entry = entry;
1120
1121         entry = create_proc_entry("stat", 0700, root_tux_dir);
1122
1123         entry->nlink = 1;
1124         entry->data = NULL;
1125         entry->read_proc = stat_read_proc;
1126         entry->write_proc = stat_write_proc;
1127
1128         stat_entry = entry;
1129
1130         /*
1131          * Create entries for all existing threads.
1132          */
1133         for (i = 0; i < CONFIG_TUX_NUMTHREADS; i++)
1134                 register_tux_proc(i);
1135 }
1136
1137 void start_sysctl(void)
1138 {
1139         init_tux_proc();
1140         tux_table_header = register_sysctl_table(tux_root_table,1);
1141 }
1142
1143 void end_sysctl(void)
1144 {
1145         cleanup_tux_proc();
1146         unregister_sysctl_table(tux_table_header);
1147 }
1148
1149