BBS水木清华站∶精华区

发信人: reden (鱼 ~ 看流星和她的故事), 信区: Linux 
标  题: Linux Remote-Boot mini-HOWTO(5/7) 
发信站: BBS 水木清华站 (Sun Oct 18 20:39:15 1998) WWW-POST 
 
4. The Configuration How-To 
 
First, arrange to have the following two machines within arm's reach:  
 
     the server, usually a Unix or Windows NT machine  
     the client, a PC with a bootprom enabled, and nothing valuable on the  
hard disk.  
 
If you want to test the configuration but you do not yet have a bootprom, you  
can download the TCP/IP BootProm demo diskette 
from InCom GmbH at http://www.incom.de. This diskette will make your computer  
behave like if it had a TCP/IP 
Bootprom plugged in. 
 
If you already have a Boot ROM, you need to enable it. If you are using Incom  
TCP/IP Bootprom, you can do that using a special 
program from your network card manufacturer. If you have a PXE Bootprom, you  
can do it simply from BIOS setup, by changing 
the default boot device. 
 
For student computers, we configured the boot on network first, and disabled  
hard-disk and floppy-disk boot. For assistant 
computers, we also configured network-boot first, but we allow hard-disk and  
floppy-disk boot. 
 
4.1 Server-side configuration 
 
On the server, you will need the following services:  
 
   1.A BOOTP/DHCP server  
   2.May be a Proxy DHCP server  
   3.A TFTP server  
 
Note for PXE Boot ROM users: We found after severals hours of tedious search  
that PXE Boot ROMs with version before 
0.99 do not follow the IP protocol and discard all packets that have the  
Don't Fragment (DF) flag set. That means, you will have 
to disable Path MTU Discovery on the server, or the Boot ROM will not see any  
of its packets. On Solaris, use ndd /dev/ip 
ip_path_mtu_discovery to see if you have it enabled and ndd -set /dev/ip  
ip_path_mtu_discovery 0 to 
disable it. However, this fix only works for non-broadcast packets (ask SUN  
why...). That means, it will work for TFTP but not 
for DHCP :-(. Intel has recently fixed this bug, and if you bought your  
computer after June 1998, you surely have a corrected PXE 
implementation. 
 
Setting up DHCP 
 
The role of the DHCP server is to give to the client an IP address and to  
make it load the file named bpbatch.P from the 
TFTP server. DHCP is a superprotocol over BOOTP. If you are using InCom  
TCP/IP Bootprom, you may live without DHCP 
(using an old BOOTP server). 
 
On Windows NT, you will probably use the native DHCP server. If you are using  
InCom TCP/IP Bootprom, you will have to use 
a special trick to specify the boot file name (get more info from InCom WWW  
site). If you are using a PXE Bootrom, you will 
need a Proxy DHCP server, but no other trick is needed as the boot file name  
will be provided by the Proxy DHCP server. 
 
On Linux, the best choice is the standard DHCP server from the Internet  
Software Consortium. If you are using a PXE Bootrom, 
in addition to the usual options, you will need to add the following ones:  
 
     option dhcp-class-identifier "PXEClient"  
     option vendor-encapsulated-options ff;  
 
On Solaris, you can either use the Internet Software Consortium DHCP server  
(available on the Web), or use Solaris DHCP 
server (available since Solaris 2.5). However, as Solaris DHCP server does  
not seems to be able to insert a client class identifier 
in its DHCP offer, you must install a Proxy DHCP server. Morever, this Proxy  
DHCP server must reside on another computer 
since Solaris DHCP server locks the DHCP port. 
 
We suggest giving infinite lease time for remote-boot clients. Don't forget  
that BOOTP/DHCP requests are bounded by subnets. 
If the client and the server do not reside on the same subnet, you should  
install a BOOTP/DHCP Relay agent on any computer 
between the two. For now, just assume that both machines are on the same  
subnet. 
 
Setting up a Proxy DHCP 
 
The role of the Proxy DHCP server is to overcome limitions of some DHCP  
servers and to provide PXE specific extensions. A 
proxy DHCP server only makes sense for a PXE Boot rom. 
 
As Bp 
 
As BpBatch itself is quite powerfull, you wont need to use any PXE specific  
DHCP extension (menus, etc.). However, if your 
DHCP server is not able to show minimal PXE compliance, you will need a Proxy  
DHCP server or your PXE Boot ROM will not 
accept to go further. 
 
On Windows NT, you can try to use Intel WfM PDK (available from their web  
site), but it is not very easy to use. We rather 
suggest having a Linux machine on the subnet and using our small Proxy DHCP.  
The major advantage of our Proxy DHCP 
Server for BpBatch is that our server will let you specify an option 155  
vendor tag that will be interpreted by BpBatch as a 
command line. 
 
On Linux and Solaris, you can run our Proxy DHCP program, that simply takes  
as argument the TFTP server IP address, boot file 
name and optional arguments, and does everything for you. If the DHCP port on  
the server is already requested by another 
daemon, the proxy DHCP server will run on port 4011. In this case, it is  
necessary that the other daemon on DHCP port answer a 
DHCP offer with client class PXEClient so that the PXE client knows that it  
must try on port 4011. 
 
If you want to understand better PXE extensions to DHCP, there is an  
extensive description available on Intel WWW site. 
However, be warned that the documents are quite confusing, as the protocol  
has been extended to a number of optional stages, in 
order to allow for a maximal flexibility. The key to understand it is that  
all what a PXE client needs is a complete enhanced 
DHCP answer. If it receives only a standard DHCP offer, it will look further  
until it gets  
 
   1.a client class (T60) set to PXEClient  
   2.vendor encapsulated options (T43) (possibly empty, ie. hex ff)  
   3.a non-empty boot filename  
 
The PXE specific negociation ends as soon as all these infos are received,  
but can lead to a very complex process (install server 
discovery, etc.) if some are missing. 
 
Setting up TFTP 
 
The TFTP server is a very simple file server. In its basic version, TFTP use  
512 bytes data blocks, which are quite inefficients. 
InCom TCP/IP Bootprom and PXE Boot ROMs allow to use larger blocks (1408  
bytes), which speeds up transfers a lot. 
However, this can only work with an enhanced TFTP server. 
 
On Windows NT, we suggest using InCom enhanced TFTP server, available on  
their web site. 
 
On Linux, you can use our enhanced TFTP server, available at 
http://cuiwww.unige.ch/info/pc/remote-boot/soft/etftpd.tar.gz. 
 
On Solaris, you should use InCom enhanced TFTP serer, available on the  
utility disk provided with the TCP/IP Bootprom. 
 
If you prefer using a standard TFTP daemon, remove the P in all boot image  
name extensions, in order to tell the Bootprom to use 
only the standard TFTP port (This trick was introduced by InCom GmbH for the  
TCP/IP Bootprom. We still use it as an easy 
way to select the default TFTP port with PXE bootproms). 
 
4.2 Client-side configuration 
 
First, we will do set up the part common to all operating systems, ie. the  
batch-file interpreter. Then, for each operating system, 
we will go through the following steps:  
 
   1.Setup a stand-alone client  
   2.Save its configuration on the server  
   3.Test it as a remote-boot client  
   4.Adapt it so that it works for any similar client machine  
 
Once this is done, you will be able to setup any supplemental client just by  
plugging a Boot ROM in it (or buying a Wired for 
Management ready computer...) and adding one line in the DHCP configuration  
file. 
 
Our examples assume that you have a hard disk of 1.4 Gb or more. If you have  
less, reduce the sizes of the partitions, but 
remember the you need to leave a few hundreds megabytes unallocated (that is,  
the last partition must not take up to the last 
cylinder) to leave free room for the special cache partition. Moreover, as  
the cache always starts at the cylinder following the last 
allocated cylinder, if you do not use the same total size for all your tests,  
you will have to download several times the same files 
(the cache will be automatically cleared). 
 
Never despair. If you can't get it to work, first look in the Troubleshooting  
section if your problem is not already solved (get the 
latest version from the Web). Then, take a look in the BpBatch forum. Perhaps  
someone else had the same troubles as you have, 
and the answer can be found in the forum. Forum's URL : 
http://cuiwww.unige.ch/info/pc/remote-boot/forum/. If it still does not work,  
think about monitoring 
network traffic for network related problems (use tcpdump on Linux or snoop  
on Solaris). If you really cannot get it to work, 
you can send an E-mail to David.Clerc@cui.unige.ch or Marc.VuilleumierStuckelb 
erg@cui.unige.ch. 
If your problem is strictly related with the remote-boot configuration and if  
we are not overflowed, we will try to solve your 
problem. 
 
4.3 Setting Up the Boot Process 
 
Get the BpBatch software, either as .zip or as .tar.gz. The executables are  
available at  
 
     http://cuiwww.unige.ch/info/pc/remote-boot/soft/bpb-exe.zip  
     http://cuiwww.unige.ch/info/pc/remote-boot/soft/bpb-exe.tar.gz  
 
The source code (Assembler and C) is also available on request. 
 
In the server /tftpboot directory, put the following three special boot  
images, which together make our pre-boot batch file 
interpreter:  
 
     bpbatch.P, the dynamic loader (respect the uppercase !)  
     bpbatch.ovl, the relocated interpreter  
     bpbatch.hlp, the on-line help file  
 
Then add an entry in the DHCP configuration file for your client, with the  
boot file set to "bpbatch.P". Define a vendor option 
tag 155 (decimal) with the value "-i" (on the standard DHCP server, this is  
done by the following command: option 
option-155 "-i";). It is interpreted by bpbatch as the command line, and -i  
stands for "interactive". 
 
Boot the client computer. You might shortly see  
 
     The Boot ROM copyright  
     The string DHCP while the client waits for a DHCP reply  
     The string TFTP while the client waits for the first TFTP packet  
     The string Loading BpBatch while the loader download the interpreter  
     And finaly our banner, followed by a nice greather-than prompt  
 
Congratulations ! You have started the batch interpreter... If you are  
curious about what you can do with it, continue reading the 
next section. If you are on a hurry, skip it and go directly install the  
operating system of your choice. If you have any doubt about a 
command within the interpreter, type help. 
 
Note that you can run the same interpreter within DOS and Linux by running  
the MrBatch program. There are a only very few 
differences (the Linux version do not have graphics support and the DOS  
version can only send BOOTP and TFTP requests if the 
BootProm is not hidden by the operating system). 
 
It may be a good idea to read now the section about the Syntax Rules of  
BpBatch, and in particular the paragraphs on File 
References and on The Cache Filesystem. This will help you understand the  
examples. 
 
Once all operating systems will be set up, you will have to make a menu to  
let the user choose the one he wants. You should be 
able to discover by yourself how to make such a menu. All necessary commands  
are documented at the end of this document. 
 
Discovering BpBatch 
 
Try to type LogVars. You should get about thirty variables listed. Roughly,  
the first are BpBatch settings, then come all 
parameters extracted from the BOOTP/DHCP reply, and the last variable is a  
list of disks sizes, in Megabytes. 
 
Type GetPartitions part, then LogVars again. There should be one more  
variable containing the list of defined 
partitions on your first hard-drive. Assuming that the first partition is  
either BIGDOS, FAT32 or LINUX-EXT2, try LogDir 
"{:1}" to get the content of the root directory, then LogDir "{:1}/usr" if  
there is an usr directory. You can even try 
LogTree "{:1}/etc" to get a directory tree. 
 
Put a GIF file (format GIF-87a, interlaced or not, but NOT GIF-89a) on your  
TFTP server. We will suppose that the file is named 
image.gif. You can copy it wherever you want with the following command: Copy  
"image.gif" 
"{:1}/temp/image.gif". Or you can use it directly from the server. Now type  
Logvars "V*" and look at the value of 
the VESA variable. If it is On, which is most probable, that means you have a  
VESA-compliant video adapter. You can list the 
available video modes using Echo "$VESA-Modes". To display your image try the  
following command: DrawGif 
"image.gif". The image should be on the upper left corner of the screen. You  
can draw it on another place by specifying X 
and Y coordinates after the image name. You can also draw text with DrawText  
200 200 "Hello world" yellow. 
Or draw an empty window with DrawWindow 200 200 300 150. To insert a title  
when you create a new window, try 
DrawWindow 200 200 300 150 "My Window". When you are tired of graphic mode,  
simply type CloseGraph. 
 
Note on graphics : by default, all graphical routines work in the 800x600  
VESA mode (with 256 colors), which is the first field of 
the VESA-Modes variable. If you want to use a different video mode, change  
the variable in order to have the requested video 
mode as the first field of the list. 
 
Now take a text editor, and create a file named test.bpb in the tftpboot  
directory with the following content:  
 
 
 
     :again 
     DrawWindow 150 200 400 160 "Identity check" 
     TextAttr Black LightGray 
     At 15,20 Print "Username : " 
     Input username 8 
     At 17,20 Print "Password : " 
     Getpasswd userpass 8 
     if "$username" != "smith" goto again 
     if not "$userpass" match-passwd "BpR8oiIlRR9bo" goto again 
     # 
     clear 
     DrawWindow 200 200 150 100 green blue "Congratulations" 
     DrawText 220 250 "You got it !" yellow 
     WaitForKey 3 
     CloseGraph 
     interact 
 
 
 
In your BOOTP/DHCP configuration, change the option-155 from "-i" to "test",  
and reboot the client computer. The small 
script should run automatically, and ask you for a username and password. If  
you do not type smith and justdoit, you wont 
be able to boot the computer. Later you will learn how to use a Unix, NT or  
Radius server to check valid user names. 
 
4.4 Setting Up Linux 
 
In order to set up Linux, you will need to boot the floppy disk provided with  
the RedHat Linux distribution. BpBatch includes a 
command that can redirect the boot to the floppy: FloppyBoot. Unfortunately,  
it does not seem to work correctly with this 
special boot floppy (any suggestion is welcome to fix this). Consequently,  
you will probably need to boot a computer without 
bootprom for this first part of Linux setup. 
 
Set up RedHat Linux on your client, with network support, and any packages  
you may want. You may want to recompile the 
kernel to better fit your hardware, but it is not necessary. 
 
Configuring the Client 
 
It is probably a good idea to include BOOTP support to the kernel, so that  
you do not have to customize the client IP address 
manually. 
 
In order to reduce network load, you might also want to setup the filecache  
for caching on the hard disk files that are loaded 
by NFS. Roughly, the principle of the filecache is that whenever a symbolic  
link from the cache subdirectory is followed, it is 
replaced by its target. If the target is itself a subdirectory, each entry of  
the subdirectory becomes a symbolic link to the original 
entry of the foreign filesystem. The filecache has been written by Unifix  
GmbH, and is part of Unifix Linux 2.0. It is freely 
distributable, and you can get the necessary files from 
http://cuiwww.unige.ch/info/pc/remote-boot/soft/filecache.tar.gz. In order to  
use the filecache, 
you have to  
 
     apply a patch to the kernel (file patch-filecache), enable filecache  
support through make config or whatever 
     you prefer, and recompile the kernel  
     copy the filecache binary file to /sbin  
     create a mount point called /mnt/nfs (using mkdir)  
     copy filecache.conf to /etc. This file contains the following lines:  
 
     Max 100 MB 50 % # 
     Cache /mnt/nfs/usr /usr 
     Cache /mnt/nfs/opt /opt 
 
     copy the content of /usr and /opt to the server, export them read-only  
with anon=0 (for allowing root access) and 
     mount them under /mnt/nfs (add a line for that in /etc/fstab)  
     rename /usr as /usr.orig  
     link /usr to /mnt/nfs/usr  
     rename /opt as /opt.orig  
     link /opt to /mnt/nfs/opt  
     ensure that /usr and /opt are not empty and contains the correct  
directories  
     recursively remove /usr.orig and /opt.orig  
     copy filecache.init to /etc/rc.d/init.d  
     And finally link /etc/rc.d/rc3.d/S35filecache to /etc/rc.d/init.d/filecac 
he.init  
 
If you successfully followed each of these steps, you should have the  
filecache working next time you boot, as long as you do not 
forget to use your patched kernel. 
 
Testing the Configuration 
 
Copy your compressed kernel image (zImage, bzImage, vmlinuz or whatever you  
call it) to the server /tftpboot 
directory as linux.krn. If you had to unplug the bootprom from the PC, you  
can now plug it again. When BpBatch starts, 
type LinuxBoot "linux.krn" "root=/dev/hda1 BOOT_IMAGE=linux" (assuming that  
the root ext2 filesystem 
is on the first partition). Alternatively, if you did setup your  
configuration on a computer without bootprom, just boot let it boot using 
the loader you installed (lilo, ...). But in the later case, if you want the  
filecache to work, you should have explicitely installed your 
kernel with filecache support at the right place. 
 
Wait until the system comes up. If you installed the filecache, you can check  
that /usr has exploded into a directory with some 
symlinks and some already-exploded directories. Now start the programs that  
the end-users will use most of the time, in order to 
load them once for all to the hard disk. 
 
You can still make adjustements to your configuration, like on any  
stand-alone linux station. 
 
Building the Disk Image 
 
When you are happy with your configuration, login as root, go to the /tmp  
directory and run our mrzip program. MrZip is a 
command interpreter like BpBatch, but it can understand more commands than  
BpBatch does. In particular, it can understand 
the following commands:  
 
 
 
     showlog 
     filter -"tmp/*" 
     filter -"var/log/*" 
     fullzip "/" "/tmp/linux.imz" 
 
 
 
This will create a disk image in /tmp/linux.imz. Move it to the server  
/tftpboot directory. Then copy the following 
batch file to /tftpboot/linux.bpb:  
 
 
 
     hidelog 
     setpartitions "linux-ext2:992 linux-swap:32" 
     fullunzip "linux.imz" 1 
     clean 2 
     linuxboot "linux.krn" "root=/dev/hda1 BOOT_IMAGE=linux" 
 
 
 
The BOOT_IMAGE argument is to stay compatible with lilo for RedHat 5.1 and  
later rc.sysinit. 
 
Your remote-boot linux configuration is ready ! You can now either set the  
BOOTP-option-155 to "linux", or type include 
"linux.bpb" from within BpBatch to test it. 
 
System Maintenance and Upgrades 
 
If you want later to upgrade software, install bug fixes and security fixes,  
proceed as follow:  
 
     Remote-boot a client computer to get a fresh linux install  
     Make your changes  
     Redo the disk image  
     Copy the new image in place of the old one on the server  
 
That means, you can upgrade software on your server-based configuration as if  
it were a purely local install. 
 
4.5 Setting up DOS 6 and Windows 3.1 
 
On the client computer, boot on your favorite dos floppy disk (either remove  
the bootprom or type FloppyBoot within 
BpBatch). Format the dos partition of your hard-drive with the /S option, in  
order to put the operating system on it. The size of the 
partition is not important, as disk archives created with MrZip Create a DOS  
subdirectory, copy DOS in it. Install your favorite 
network client (for instance Microsoft LanManager), Windows 3.1, and so on.  
If you use Microsoft LanManager, do not use 
DHCP for the IP configuration as it is a very poor implementation that will  
almost surely fail with reasonable network load. To do 
that, add the following lines in your protocol.ref file, in the section that  
loads tcptsr (of course, replaces the xxx by your 
true IP parameters):  
 
        IPADDRESS0 = xxx xxx xxx xxx 
        SUBNETMASK0 = 255 255 xxx xxx 
        DEFAULTGATEWAY0 = xxx xxx xxx xxx 
        DISABLEDHCP = 1 
 
Do not be afraid to use EMM386 to optimize the memory usage, and even to  
include the area where you put your network adapter 
ROM, since it is not used anymore at this time. But carefully exclude the  
network adapter RAM, or you will not be able to 
connect to your server. Use the NOEMS parameter. 
 
If you want to ensure that the client machine cannot be used without a valid  
login name, download our nobreak pseudo-device 
driver (available at http://cuiwww.unige.ch/info/pc/remote-boot/soft/nobreak.z 
ip) and run it at the 
beginning of your config.sys. Then add something like this to your  
autoexec.bat:  
 
 
 
     rem -- we use the dummy file c:\logged as a flag 
     del c:\logged >nul 
     :loginneeded 
     cls 
     echo Please type in your login name and password 
     echo. 
     net logon * 
     rem -- the login script should have created c:\logged 
     if not exist c:\logged goto loginneeded 
     del c:\logged 
     rem -- now enable break again 
     echo Yes >NOBRK 
 
 
 
Ensure that your client boot well by rebooting the client and evaluating the  
following commands within BpBatch interactive 
mode:  
 
        HideBootprom 
        HdBoot 
 
Building the Disk Image 
 
On the server, make a share called admin for instance, on which you will put  
some stuff for the system administrator. If the 
server is a Unix machine, it is a good opportunity to put in admin a softlink  
to the /tftpboot subdirectory, so that you can put 
images in it directly from the client. Within admin, create a /utils  
subdirectory and put the following files in it:  
 
     mrbatch.exe, the DOS version of BpBatch  
     mrzip.exe, the DOS version of the program for building disk images  
     bpbatch.hlp, the on-line help file  
 
You might also like to put in the same directory a simple MrZip script named  
zipdos.mrz file that contains the commands 
needed for building a DOS image, like this one:  
 
 
 
     showlog 
     filter -"lanman.dos/lmuser.ini" 
     filter -"temp/*" 
     filter -"*.swp" 
     fullzip "c:/" "L:/tftpboot/dos.imz" 
 
 
 
Now go back to your client, mount the admin volume on drive L:, go to your  
utils directory and type the following command:  
 
        mrzip -b zipdos 
 
One minute later, you will have a new file in the server /tftpboot  
subdirectory called dos.imz, which is a compressed 
image of your hard disk. Copy the following batch file to /tftpboot/dos.bpb:  
 
 
 
 
     hidelog 
     setpartitions "bigdos:1024" 
     setbootpart 1 
     fullunzip "dos.imz" 1 
     hidebootprom 
     hdboot :1 
 
 
 
Your remote-boot DOS configuration is ready ! You can now either set the  
BOOTP-option-155 to "dos", or type include 
"dos.bpb" from within BpBatch to test it. 
 
Adapting the configuration for other machines 
 
If you want to customize some settings according to the machine, typically  
the IP settings since Micro$oft DHCP is buggy, you 
can setup BpBatch to change some files before booting. Firsti go to the  
lanman.dos directory and do  
 
        copy *.ini *.ref 
 
Then edit the .ref files and replace all fixed parameters with BOOTP variable  
names as in the following examples:  
 
        computername = ${BOOTP-Host-Name} 
        ipaddress0 = ${MS-IPAddress} 
        subnetmask0 = ${MS-IPSubnet} 
        defaultgateway = ${MS-IPRouter} 
 
Then rebuild the disk image as previously. Note that for IP parameters, we do  
not use the BOOTP variables directly because 
LanManager needs then as space-separated numbers instead of dot-separated  
numbers. Change dos.bpb to the following:  
 
 
 
     hidelog 
     setpartitions "bigdos:1024" 
     setbootpart 1 
     fullunzip "dos.imz" 1 
     set MS-IPAddress="$BOOTP-Your-IP"/.= / 
     set MS-IPSubnet="$BOOTP-Subnet-Mask"/.= / 
     set MS-IPRouter="$BOOTP-Routers"/.= / 
     patch "{:1}lanman.dos/protocol.ref" "{:1}lanman.dos/protocol.ini" 
     patch "{:1}lanman.dos/tcpputils.ref" "{:1}lanman.dos/tcputils.ini" 
     patch "{:1}lanman.dos/lanman.ref" "{:1}lanman.dos/lanman.ini" 
     hidebootprom 
     hdboot :1 
 
 
 
If you prefer, you can also put the .ref files in the server /tftpboot  
directory instead of in the disk image. 
 
We like to be able to easily change the computers configuration without  
rebuilding the image. To do that, copy your 
autoexec.bat and config.sys as autoexec.ref and config.ref to the server  
/tftpboot and add the 
following two lines to the batch file above:  
 
        patch "autoexec.ref" "{:1}autoexec.bat" 
        patch "config.ref" "{:1}config.sys" 
 
You can then freely change the files and even customize them with  
machine-dependant values obtained from BOOTP. 
 
After making any change to the client machine configuration, do not forget to  
rebuild the disk image using mrzip if you want to 
preserve your changes. 
 
System Maintenance and Upgrades 
 
If you want later to add new software or change anything else, proceed as  
follow:  
 
     Remote-boot a client computer to get a fresh install  
     Make your changes  
     Redo the disk image  
     Copy the new image in place of the old one on the server  
 
That means, you can upgrade software on your server-based configuration as if  
it were a purely local install. 
 
 
-- 
    白马带著她一步步的回到中原。白马已经老了,只能慢慢的走, 
但终是能回到中原的。江南有杨柳、桃花,有燕子、金鱼…… 
汉人中有的是英俊勇武的少年,倜傥潇洒的少年……但这个美 
丽的姑娘就像古高昌国人那样固执: 
 
    「那都是很好很好的,可是我偏不喜欢。」  
 
※ 来源:·BBS 水木清华站 bbs.net.tsinghua.edu.cn·[FROM: 202.99.18.67]  

BBS水木清华站∶精华区