This commit was manufactured by cvs2svn to create branch 'fedora'.
[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 unsigned int log_cpu_mask = ~0;
57 unsigned int tux_compression = 0;
58 unsigned int tux_noid = 0;
59 unsigned int tux_cgi_inherit_cpu = 0;
60 unsigned int tux_cgi_cpu_mask = ~0;
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 #if 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_CGI_CPU_MASK,
626                 "cgi_cpu_mask",
627                 &tux_cgi_cpu_mask,
628                 sizeof(int),
629                 0644,
630                 NULL,
631                 proc_dointvec,
632                 &sysctl_intvec,
633                 NULL,
634                 NULL,
635                 NULL
636         },
637         {       NET_TUX_ZEROCOPY_HEADER,
638                 "zerocopy_header",
639                 &tux_zerocopy_header,
640                 sizeof(int),
641                 0644,
642                 NULL,
643                 proc_dointvec,
644                 &sysctl_intvec,
645                 NULL,
646                 NULL,
647                 NULL
648         },
649         {       NET_TUX_ZEROCOPY_SENDFILE,
650                 "zerocopy_sendfile",
651                 &tux_zerocopy_sendfile,
652                 sizeof(int),
653                 0644,
654                 NULL,
655                 proc_dointvec,
656                 &sysctl_intvec,
657                 NULL,
658                 NULL,
659                 NULL
660         },
661         {       NET_TUX_MAX_FREE_REQUESTS,
662                 "max_free_requests",
663                 &tux_max_free_requests,
664                 sizeof(int),
665                 0644,
666                 NULL,
667                 proc_dointvec,
668                 &sysctl_intvec,
669                 NULL,
670                 NULL,
671                 NULL
672         },
673         {       NET_TUX_ALL_USERSPACE,
674                 "all_userspace",
675                 &tux_all_userspace,
676                 sizeof(int),
677                 0644,
678                 NULL,
679                 proc_dointvec,
680                 &sysctl_intvec,
681                 NULL,
682                 NULL,
683                 NULL
684         },
685         {       NET_TUX_REDIRECT_LOGGING,
686                 "redirect_logging",
687                 &tux_redirect_logging,
688                 sizeof(int),
689                 0644,
690                 NULL,
691                 proc_dointvec,
692                 &sysctl_intvec,
693                 NULL,
694                 NULL,
695                 NULL
696         },
697         {       NET_TUX_IGNORE_QUERY,
698                 "ignore_query",
699                 &tux_ignore_query,
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                 "referer_logging",
711                 &tux_referer_logging,
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                 "cpu_offset",
723                 &tux_cpu_offset,
724                 sizeof(int),
725                 0644,
726                 NULL,
727                 proc_dointvec,
728                 &sysctl_intvec,
729                 NULL,
730                 NULL,
731                 NULL
732         },
733         {       NET_TUX_REFERER_LOGGING,
734                 "ftp_login_message",
735                 &tux_ftp_login_message,
736                 sizeof(int),
737                 0644,
738                 NULL,
739                 proc_dointvec,
740                 &sysctl_intvec,
741                 NULL,
742                 NULL,
743                 NULL
744         },
745         {       NET_TUX_MAX_HEADER_LEN,
746                 "max_header_len",
747                 &tux_max_header_len,
748                 sizeof(int),
749                 0644,
750                 NULL,
751                 proc_dointvec,
752                 &sysctl_intvec,
753                 NULL,
754                 NULL,
755                 NULL
756         },
757         {0,0,0,0,0,0,0,0,0,0,0} };
758         
759         
760 static ctl_table tux_dir_table[] = {
761         {NET_TUX, "tux", NULL, 0, 0555, tux_table,0,0,0,0,0},
762         {0,0,0,0,0,0,0,0,0,0,0}
763 };
764
765 static ctl_table tux_root_table[] = {
766         {CTL_NET, "net", NULL, 0, 0555, tux_dir_table,0,0,0,0,0},
767         {0,0,0,0,0,0,0,0,0,0,0}
768 };
769
770
771 static struct proc_dir_entry * root_tux_dir;
772 static struct proc_dir_entry * log_cpu_mask_entry;
773 static struct proc_dir_entry * stat_entry;
774 static struct proc_dir_entry * tux_dir [CONFIG_TUX_NUMTHREADS];
775 static struct proc_dir_entry * listen_dir [CONFIG_TUX_NUMTHREADS];
776
777 tux_socket_t tux_listen [CONFIG_TUX_NUMTHREADS][CONFIG_TUX_NUMSOCKETS] =
778  { [0 ... CONFIG_TUX_NUMTHREADS-1] = { {&tux_proto_http, 0, 80, NULL}, } };
779
780 #define HEX_DIGITS 8
781
782 static int hex_read_proc (char *page, char **start, off_t off,
783                         int count, int *eof, void *data)
784 {
785         if (count < HEX_DIGITS+1)
786                 return -EINVAL;
787         return sprintf (page, "%08x\n", *(unsigned int *)data);
788 }
789
790 static int hex_write_proc (struct file *file, const char *buffer,
791                                         unsigned long count, void *data)
792 {
793         char hexnum [HEX_DIGITS];
794         unsigned int new_value;
795         unsigned int i, full_count = count;
796
797         if (!count)
798                 return -EINVAL;
799         if (count > HEX_DIGITS)
800                 count = HEX_DIGITS;
801         if (copy_from_user(hexnum, buffer, count))
802                 return -EFAULT;
803
804         /*
805          * Parse the first 8 characters as a hex string, any non-hex char
806          * is end-of-string. '00e1', 'e1', '00E1', 'E1' are the same.
807          */
808         new_value = 0;
809
810         for (i = 0; i < count; i++) {
811                 unsigned int c = hexnum[i];
812
813                 switch (c) {
814                         case '0' ... '9': c -= '0'; break;
815                         case 'a' ... 'f': c -= 'a'-10; break;
816                         case 'A' ... 'F': c -= 'A'-10; break;
817                 default:
818                         goto out;
819                 }
820                 new_value = (new_value << 4) | c;
821         }
822 out:
823         *(int *)data = new_value;
824
825         return full_count;
826 }
827
828 #define LINE_SIZE 1024
829 #define LINE_MASK (LINE_SIZE-1)
830
831 static int print_request_stats (threadinfo_t *ti, char *page, unsigned int skip_count, unsigned int max_count)
832 {
833         struct list_head *head, *curr;
834         tux_req_t *req;
835         unsigned int count = 0, size, line_off, len;
836         char stat_line [LINE_SIZE];
837
838         if (!max_count)
839                 BUG();
840
841         head = &ti->all_requests;
842         curr = head->next;
843
844         while (curr != head) {
845                 req = list_entry(curr, tux_req_t, all);
846                 curr = curr->next;
847                 count++;
848                 if (count <= skip_count)
849                         continue;
850                 line_off = 0;
851 #define SP(x...) \
852         line_off += sprintf(stat_line + line_off, x)
853
854                 if (req->proto == &tux_proto_http)
855                         SP("0 ");
856                 else
857                         SP("1 ");
858         
859                 SP("%p ", req);
860                 SP("%d ", req->atom_idx);
861                 if (req->atom_idx >= 1)
862                         SP("%p ", req->atoms[0]);
863                 else
864                         SP("........ ");
865                 if (req->atom_idx >= 2)
866                         SP("%p ", req->atoms[1]);
867                 else
868                         SP("........ ");
869                 if (!list_empty(&req->work))    SP("W");        else SP(".");
870                 if (!list_empty(&req->free))    SP("F");        else SP(".");
871                 if (!list_empty(&req->lru))     SP("L");        else SP(".");
872                 if (req->keep_alive)            SP("K");        else SP(".");
873                 if (req->idle_input)            SP("I");        else SP(".");
874                 if (timer_pending(&req->keepalive_timer))
875                                                 SP("T(%lu/%lu)",jiffies,req->keepalive_timer.expires);  else SP(".");
876                 if (req->wait_output_space)     SP("O");        else SP(".");
877                 if (timer_pending(&req->output_timer))
878                                                 SP("T");        else SP(".");
879                 SP(" %d ", req->error);
880                 SP(" %d ", req->status);
881
882 #define SP_HOST(ip,port) \
883                 SP("%d.%d.%d.%d:%d ",NIPQUAD(ip),port)
884
885                 if (req->sock) {
886                         if (req->sock->sk)
887                                 SP("%d:", req->sock->sk->sk_state);
888                         else
889                                 SP("-2:");
890                 } else
891                         SP("-1:");
892                 SP_HOST(req->client_addr, req->client_port);
893
894                 SP("%Ld ", req->total_file_len);
895                 SP("%Ld ", req->in_file.f_pos);
896                 if (req->proto == &tux_proto_http) {
897                         SP("%d ", req->method);
898                         SP("%d ", req->version);
899                 }
900                 if (req->proto == &tux_proto_ftp) {
901                         SP("%d ", req->ftp_command);
902                         if (req->data_sock) {
903                                 if (req->data_sock->sk)
904                                         SP("%d:",req->data_sock->sk->sk_state);
905                                 else
906                                         SP("-2:");
907                                 if (req->data_sock->sk)
908                                         SP_HOST(inet_sk(req->data_sock->sk)->daddr,
909                                                 inet_sk(req->data_sock->sk)->dport);
910                                 else
911                                         SP("-1:-1 ");
912                         } else
913                                 SP("-1 ");
914                 }
915                 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);
916
917                 SP("%d\n", req->parsed_len);
918                 len = req->headers_len;
919                 if (len > 500)
920                         len = 500;
921                 SP("\n%d\n", len);
922                 memcpy(stat_line + line_off, req->headers, len);
923                 line_off += len;
924                 len = req->objectname_len;
925                 if (len > 100)
926                         len = 100;
927                 SP("\n%d\n", len);
928                 memcpy(stat_line + line_off, req->objectname, len);
929                 line_off += len;
930                 SP("\n\n<END>");
931                 if (line_off >= LINE_SIZE)
932                         BUG();
933                 Dprintk("printing req %p, count %d, page %p: {%s}.\n", req, count, page, stat_line);
934                 size = sprintf(page, "%-*s\n", LINE_SIZE-1, stat_line);
935                 if (size != LINE_SIZE)
936                         BUG();
937                 page += LINE_SIZE;
938                 if (count-skip_count >= max_count)
939                         break;
940         }
941
942         Dprintk("count: %d.\n", count-skip_count);
943         return count - skip_count;
944 }
945
946 static int stat_read_proc (char *page, char **start, off_t off,
947                         int max_size, int *eof, void *data)
948 {
949         unsigned int i, nr_total = 0, nr, nr_off, nr_skip, size = 0, nr_wanted;
950
951         Dprintk("START, page: %p, max_size: %d, off: %ld.\n", page, max_size, off);
952         *eof = 1;
953         if (max_size & LINE_MASK)
954                 return 0;
955         if (off & LINE_MASK)
956                 return 0;
957         if (!max_size)
958                 return 0;
959
960         nr_off = off/LINE_SIZE;
961
962         for (i = 0; i < nr_tux_threads; i++) {
963                 threadinfo_t *ti = threadinfo + i;
964                 spin_lock_irq(&ti->work_lock);
965                 nr = ti->nr_requests;
966                 Dprintk("ti: %p, nr: %d, nr_total: %d, nr_off: %d.\n", ti, nr, nr_total, nr_off);
967                 nr_total += nr;
968                 if (nr_off >= nr_total) {
969                         spin_unlock_irq(&ti->work_lock);
970                         continue;
971                 }
972                 nr_skip = nr_off - (nr_total - nr);
973                 nr_wanted = (max_size-size) / LINE_SIZE;
974                 Dprintk("nr_skip: %d, nr_wanted: %d.\n", nr_skip, nr_wanted);
975                 nr = print_request_stats(ti, page + size, nr_skip, nr_wanted);
976                 spin_unlock_irq(&ti->work_lock);
977                 nr_off += nr;
978                 size += nr * LINE_SIZE;
979                 Dprintk("ret: %d requests, size: %d.\n", nr, size);
980                 if (size > max_size)
981                         BUG();
982                 if (size == max_size)
983                         break;
984         }
985         Dprintk("DONE: size: %d.\n", size);
986
987         *start = page;
988
989         if (size)
990                 *eof = 0;
991         return size;
992 }
993
994 static int stat_write_proc (struct file *file, const char *buffer,
995                                         unsigned long count, void *data)
996 {
997         return -EINVAL;
998 }
999
1000 #define MAX_STRING "http://255.255.255.255:65535"
1001 #define MAX_STRINGLEN (sizeof(MAX_STRING))
1002
1003 #define INACTIVE_1 "[inactive]\n"
1004 #define INACTIVE_2 "0\n"
1005
1006 static int listen_read_proc (char *page, char **start, off_t off,
1007                         int count, int *eof, void *data)
1008 {
1009         tux_socket_t *listen = data;
1010
1011         if (count < MAX_STRINGLEN)
1012                 return -EINVAL;
1013
1014         if (!listen->proto)
1015                 return sprintf(page, INACTIVE_1);
1016
1017         return sprintf (page, "%s://%u.%u.%u.%u:%hu\n", listen->proto->name,
1018                         HIPQUAD(listen->ip), listen->port);
1019 }
1020
1021 static int listen_write_proc (struct file *file, const char *buffer,
1022                                         unsigned long count, void *data)
1023 {
1024         char string [MAX_STRINGLEN];
1025         unsigned int d1, d2, d3, d4;
1026         unsigned short port;
1027         tux_socket_t *listen = data;
1028
1029         if (!count)
1030                 return -EINVAL;
1031         if (count > MAX_STRINGLEN)
1032                 count = MAX_STRINGLEN;
1033         if (copy_from_user(string, buffer, count))
1034                 return -EFAULT;
1035         string[count] = 0;
1036
1037         if (!strcmp(string, INACTIVE_1) || !strcmp(string, INACTIVE_2)) {
1038                 listen->proto = NULL;
1039                 listen->ip = 0;
1040                 listen->port = 0;
1041                 return count;
1042         }
1043
1044 #define MK_IP(a,b,c,d) ((a << 24) | (b << 16) | (c << 8) | d)
1045
1046         if (sscanf(string, "http://%u.%u.%u.%u:%hu\n",
1047                                         &d1, &d2, &d3, &d4, &port) == 5) {
1048                 listen->ip = MK_IP(d1,d2,d3,d4);
1049                 listen->port = port;
1050                 listen->proto = &tux_proto_http;
1051                 return count;
1052         }
1053                 
1054         if (sscanf(string, "ftp://%u.%u.%u.%u:%hu\n",
1055                                         &d1, &d2, &d3, &d4, &port) == 5) {
1056                 listen->ip = MK_IP(d1,d2,d3,d4);
1057                 listen->port = port;
1058                 listen->proto = &tux_proto_ftp;
1059                 return count;
1060         }
1061         printk(KERN_ERR "tux: invalid listen-socket parameters: %s\n", string);
1062         return -EINVAL;
1063 }
1064
1065 #define MAX_NAMELEN 10
1066
1067 static void register_tux_proc (unsigned int nr)
1068 {
1069         struct proc_dir_entry *entry;
1070         char name [MAX_NAMELEN];
1071         int i;
1072
1073         if (!root_tux_dir)
1074                 TUX_BUG();
1075
1076         sprintf(name, "%d", nr);
1077
1078         /* create /proc/net/tux/1234/ */
1079         tux_dir[nr] = proc_mkdir(name, root_tux_dir);
1080
1081         /* create /proc/net/tux/1234/listen/ */
1082         listen_dir[nr] = proc_mkdir("listen", tux_dir[nr]);
1083
1084         /* create /proc/net/tux/1234/listen/ */
1085         for (i = 0; i < CONFIG_TUX_NUMSOCKETS; i++) {
1086                 sprintf(name, "%d", i);
1087                 entry = create_proc_entry(name, 0700, listen_dir[nr]);
1088
1089                 entry->nlink = 1;
1090                 entry->data = (void *)(tux_listen[nr] + i);
1091                 entry->read_proc = listen_read_proc;
1092                 entry->write_proc = listen_write_proc;
1093                 tux_listen[nr][i].entry = entry;
1094         }
1095 }
1096
1097 static void unregister_tux_proc (unsigned int nr)
1098 {
1099         int i;
1100
1101         for (i = 0; i < CONFIG_TUX_NUMSOCKETS; i++) {
1102                 remove_proc_entry(tux_listen[nr][i].entry->name,listen_dir[nr]);
1103                 tux_listen[nr][i].entry = NULL;
1104         }
1105
1106         remove_proc_entry(listen_dir[nr]->name, tux_dir[nr]);
1107
1108         remove_proc_entry(tux_dir[nr]->name, root_tux_dir);
1109 }
1110
1111 static void cleanup_tux_proc (void)
1112 {
1113         int i;
1114
1115         Dprintk("cleaning up /proc/net/tux/\n");
1116
1117         for (i = 0; i < CONFIG_TUX_NUMTHREADS; i++)
1118                 unregister_tux_proc(i);
1119         remove_proc_entry(stat_entry->name, root_tux_dir);
1120         remove_proc_entry(log_cpu_mask_entry->name, root_tux_dir);
1121         remove_proc_entry(root_tux_dir->name, proc_net);
1122 }
1123
1124 static void init_tux_proc (void)
1125 {
1126         struct proc_dir_entry *entry;
1127         int i;
1128
1129         if (root_tux_dir)
1130                 return;
1131
1132         /* create /proc/net/tux */
1133         root_tux_dir = proc_mkdir("tux", proc_net);
1134
1135         entry = create_proc_entry("log_cpu_mask", 0700, root_tux_dir);
1136
1137         entry->nlink = 1;
1138         entry->data = (void *)&log_cpu_mask;
1139         entry->read_proc = hex_read_proc;
1140         entry->write_proc = hex_write_proc;
1141
1142         log_cpu_mask_entry = entry;
1143
1144         entry = create_proc_entry("stat", 0700, root_tux_dir);
1145
1146         entry->nlink = 1;
1147         entry->data = NULL;
1148         entry->read_proc = stat_read_proc;
1149         entry->write_proc = stat_write_proc;
1150
1151         stat_entry = entry;
1152
1153         /*
1154          * Create entries for all existing threads.
1155          */
1156         for (i = 0; i < CONFIG_TUX_NUMTHREADS; i++)
1157                 register_tux_proc(i);
1158 }
1159
1160 void start_sysctl(void)
1161 {
1162         init_tux_proc();
1163         tux_table_header = register_sysctl_table(tux_root_table,1);
1164 }
1165
1166 void end_sysctl(void)
1167 {
1168         cleanup_tux_proc();
1169         unregister_sysctl_table(tux_table_header);
1170 }
1171
1172 #if CONFIG_SMP
1173 void mask_to_cpumask(unsigned int mask, cpumask_t *cpu_mask)
1174 {
1175
1176         unsigned int bit_mask, i;
1177
1178         bit_mask = 1 << 31;
1179
1180         for (i=NR_CPUS-1; i--; i >= 0) {
1181                 if(mask & bit_mask)
1182                         cpu_set(i, *cpu_mask);
1183                 else
1184                         cpu_clear(i, *cpu_mask);
1185                 mask <<= 1;
1186         }
1187
1188 }
1189 #endif
1190