免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1847 | 回复: 0
打印 上一主题 下一主题

经典问题WTO [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-02-04 16:51 |只看该作者 |倒序浏览
16.   库相关问题  
16.1  在Solaris 7下编写网络程序需要链接哪些库  
16.3  链接过程中库的顺序  
16.6  /usr/lib/ld.so.1损坏或丢失  
16.9  Solaris 8下如何配置运行时链接环境
16. 库相关问题  
16.1 在Solaris 7下编写网络程序需要链接哪些库  
Q: inet_pton()是什么库里的,为什么man手册里无对应内容  
A: scz   
这个函数比较新,还有另外几个,比如inet_ntop()。关于它们的详细介绍参看  
> 3.7 小节。文件/usr/include/arpa/inet.h中定义  
有:  
extern int inet_pton ( int, const char *, void * );  
用/usr/ccs/bin/nm工具观察三个动态链接库libresolv.so、libsocket.so、  
libnsl.so提供的全局函数  
显然,如果涉及RPC编程,必然需要libnsl.so,而inet_pton()来自libresolv.so。  
总结一下,实在不能确定的时候,编译时指定链接开关如下:  
-lsocket -lnsl -lresolv  
16.2 SUID设置和LD_LIBRARY_PATH环境变量  
Q: RedHat Linux 6.1/6.2,C编程,还有一些脚本  
   execl()以及其他exec...()执行一个SUID程序的时候,出于安全考虑,会清除  
   LD_LIBRARY_PATH环境变量,仅仅依靠系统全局设置搜索共享库。参看如下URL  
   
http://spdoc.pdc.kth.se/doc_link/C/a_doc_lib/libs/basetrf1/exec.htm
  
   现在有一个程序,需要一个正确的LD_LIBRARY_PATH环境变量设置才能运行,可是  
   由于某些原因必须做SUID设置,结果最终运行失败。我尝试在程序中putenv()、  
   setenv(),失败,显然LD_LIBRARY_PATH环境变量需要在程序加载过程中由动态链  
   接器使用,程序中的putenv()、setenv()为时已晚。  
   于是我写了一个脚本,在脚本中设置LD_LIBRARY_PATH环境变量,调用C程序,对  
   脚本做SUID设置。但是脚本的SUID设置并没有传递给子进程(这里就是那个C程序)  
A: Paul Sack   

www.google.com
用"suid shell scripts race conditions"进行搜索,查看  
BugTraq相关讨论。安全的解决办法是用C写一个SUID WRAPPER去exec...()你的C程序,  
在SUID WRAPPER中设置LD_LIBRARY_PATH环境变量。  
A: Andrew Gierth   
如果一个程序是SUID过的,将导致LD_LIBRARY_PATH环境变量被忽略,但是这不是问  
题本质所在,本质原因在于ruid不等于euid(或者rgid不等于egid)。所以wrapper中  
仅仅重置环境变量是不够的,必须想办法修改ruid等于euid。最好还是重新编译程序,  
使之不依赖于LD_LIBRARY_PATH环境变量。  
16.3 链接过程中库的顺序  
Q: 有几个库文件A.a、B.a、common.a,前两者用到了定义在后者中的例程,如果把  
   common.a放在前面,链接器报告存在无法解析的符号名,放在最后则无问题。  
A: Floyd Davidson   
   链接器按照命令行上指定顺序搜索库文件和目标文件(.a .o),二者之间的区别在  
   于.o文件被全部链接进来,而只从库文件中析取所需模块,仅当某个模块可以解  
   析当前尚未成功解析的符号时,该模块被析取后链接进来。如果库文件无法解析  
   任何当前尚未成功解析的符号,不从中析取也不发生链接。  
   Unix编程新手的常见问题是数学函数并不在标准C库中,而是在libm.a中  
   cc -lm foo.c  
   这里foo.c用到了数学库中的符号,但是链接器无法正确解析。当搜索到libm.a时,  
   来自foo.c的数学函数符号尚未出现,因此不需要析取libm.a的任何模块。接下来  
   foo.o链接进来,增加了一批尚未成功解析的符号,但已经没有libm.a可供使用了,  
   因此数学库必须在foo.o之后被搜索到。  
   cc foo.c -lm  
   在你的问题中,如果common.a首先被搜索到,因为不匹配尚未成功解析的符号,  
   而被丢弃。结果A.a和B.a真正链接进来的时候,已经没有库可以解析符号了。  
16.6 /usr/lib/ld.so.1损坏或丢失  
Q: 意外地覆盖了ld.so.1,幸运的是有一个原始备份,可我没有一个静态链接版本的  
   命令去恢复它。  
Q: 我在Solaris 2.6中做了"mv /usr/lib /usr/lib1",本意是想使用自己的库,但  
   是现在所有程序都报告"找不到/usr/lib/ld.so.1",怎么办  
A: scz   
不要重启动,立即用/usr/sbin/static/mv、/usr/sbin/static/cp命令恢复  
# ls /usr/sbin/static  
cp*   ln*   mv*   rcp*  tar*  
#  
Q: 那如果此时/usr被改名了,怎么办?  
A: faint,谁这么变态。假设/usr改名成了/faint,  
1) /faint/sbin/static/cp /faint/sbin/static/mv /tmp/mv  
2) /tmp/mv /faint /usr  
我不确定  
1) /faint/sbin/static/mv /faint /usr  
能否成功,你可以自己测试一下效果。或者  
ok boot cdrom -s (放入启动安装光盘)  
mount /dev/dsk/c0t0d0s0 /mnt (这里指定原根区对应的原始设备名)  
mv /mnt/faint /mnt/usr  
D:
[email=cirrus@SMTH]cirrus@SMTH[/email]
  
建议把/usr/sbin/static下的东西拷一份到/sbin下或者其它比较可信的跟/在同一个  
fs的目录下。装机器的时候,不管什么OS,/usr都是单独一个fs的。  
16.9 Solaris 8下如何配置运行时链接环境  
Q: 在Linux下我知道用ldconfig(8)配置运行时链接环境,但是在Solaris 8下呢  
A:   
你总是可以利用 LD_LIBRARY_PATH 环境变量,对于Solaris 8,还可以参看crle(1)  
手册页。  
A: Logan Shaw   
如果在链接时使用了"-R"和"-L"选项,则相关动态库的路径将保存在ELF文件中,于  
是以后的运行中不再需要设置环境变量去定位动态库。比如,有一个  
/usr/local/lib/libfoo.so,而你的bar程序需要这个libfoo.so,编译、链接时最好  
这样  
gcc -Wall -pipe -O3 -o bar -R/usr/local/lib -L/usr/local/lib bar.c -lfoo
_________________________________________________________________________________________________
9.    图形界面相关问题  
9.1   如何避免进入Solaris的图形界面  
9.2   Solaris 7的锁屏  
9.3   如何调整键盘重复率  
9.4   如何拔掉键盘继续运行Solaris  
9.5   Solaris下如何设置显卡分辨率  
9.6   Solaris下如何设置显示刷新率  
--------------------------------------------------------------------------  
9. 图形界面相关问题  
9.1 如何避免进入Solaris的图形界面  
Q: 我想让console保持在字符模式下,该如何做  
A: Darren Dunham   
这里有一份很好的FAQ,
http://www.wins.uva.nl/pub/solaris/solaris2.html
  
下文引自
http://www.science.uva.nl/pub/solaris/solaris2.html#q3.54
  
如何允许/禁止dtlogin?  
是否启动dtlogin可以用/usr/dt/bin/dtconfig命令进行设置,不带任何参数执行该  
命令,提示如下:  
/usr/dt/bin/dtconfig -d        (disable auto-start)  
/usr/dt/bin/dtconfig -e        (enable auto-start)  
/usr/dt/bin/dtconfig -kill     (kill dtlogin)  
/usr/dt/bin/dtconfig -reset    (reset dtlogin)  
/usr/dt/bin/dtconfig -p        (printer action update)  
/usr/dt/bin/dtconfig -inetd    (inetd.conf /usr/dt daemons)  
/usr/dt/bin/dtconfig -inetd.ow (inetd.conf /usr/openwin daemons)  
如果绝大多数时间你并不想关闭图形模式,可以在"session"菜单上选择  
"command line login"。  
A:   
更省事的办法是  
cd /etc/rc2.d  
mv S99dtlogin s99dtlogin  
Q: Solaris CDE窗口的启动与关闭  
A: tenia@一塌糊涂 1999-11-03  
用/usr/dt/bin/dtlogin  
dtlogin -daemon  从命令行启动注册窗口  
dtlogin -e       使系统自动启动注册窗口  
dtlogin -d       取消自动启动  
dtlogin -kill    杀掉注册窗口  
9.2 Solaris 7的锁屏  
Q: Solaris 7中哪个进程负责锁屏效应。7以前的版本,某些人在console登录后锁屏,  
   回家前忘记取消锁屏,我简单地杀掉xlock进程即可。但是我不知道Solaris 7中  
   该怎么做。看了看dtsession和dtscreen的一些东西,但是无论我杀掉二者中哪个  
   进程,console挂起在黑屏的无限循环中,只有鼠标光标可见  
A:   
应该是dtscreen  
9.3 如何调整键盘重复率  
Q: Ultra 5 Solaris 8 如何设置键盘重复率?我想设置重复率到最大,延迟到最小。  
A: Alan Coopersmith   
   
http://soar.Berkeley.EDU/~alanc/
  
如果是root想对系统中所有用户做此修改,编辑/etc/dt/config/Xservers,增加  
-ar1 和 -ar2选项。如果/etc/dt/config/Xservers不存在,从  
/usr/dt/config/Xservers复制一份过来。  
如果不是root,仅仅想修改自己的配置,用/usr/openwin/bin/accessx配置键盘和鼠  
标参数。  
man -M /usr/openwin/man Xsun  
    -ar1 milliseconds  
        这么多毫秒后按键开始自动重复。缺省500毫秒。参数对于x86或者PowerPC  
        无效。  
    -ar2 milliseconds  
        两次自动重复之间的时间间隔(毫秒单位)。缺省50毫秒。参数对于x86或者  
        PowerPC无效。  
man -M /usr/openwin/man accessx  
9.4 如何拔掉键盘继续运行Solaris  
Q: 我这里的E250/E3500装了Solaris后键盘都不能拔掉,一拔掉就进入OK状态。而老  
   式的SparcServer 1000E是可以不要键盘运行的,不知道要在哪里设置才能够不要  
   键盘运行?  
Q: 这里是一台Sun Ultra 5,拔掉键盘后,系统停止响应  
A: J.Keil  
拔掉键盘导致Ultra 5的console设备侦测到一次BREAK条件。BREAK条件将中断操作系  
统,使系统进入OBP(open boot prom)监视状态。如果启动内核时使用了kadb内核调  
试器,BREAK条件使系统进入kadb调试状态。  
参看kbd(1)手册页,有几种办法禁止这种行为:  
a. 永久办法  
vi /etc/default/kbd  
KEYBOARD_ABORT=disable  
/usr/bin/kbd -i (不用重新启动机器)  
b. 临时办法  
/usr/bin/kbd -a disable  
与之对应的就是  
/usr/bin/kbd -a enable  
c. 看BSM的时候找到的另外一种解决办法,在/etc/system文件中增加如下行  
set abort_enable = 0  
A:
dkoleary@mediaone.net
2001-06-02 22:09  
用kbd(1)命令  
kbd [ enable | disable | alternate ]  
enable    : 允许 STOP-A  
disable   : 禁止 STOP-A  
alternate : 允许拔掉键盘,但不禁止 STOP-A  
为了使用 alternate 选项,需要安装下列补丁  
Solaris 2.6 105924-10  
Solaris 7   107589-03  
9.5 Solaris下如何设置显卡分辨率  
A:
kougar@smth.org
  
/etc/openwin/server/etc/OWconfig  
/usr/openwin/server/etc/OWconfig  
A:
hycan@smth.org
  
/usr/sbin/m64config -prconf -propt  
/usr/sbin/m64config -res '?'  
ls -l /dev/fb (一个符号链接)  
ls -l /dev/fbs/m640 (一个符号链接)  
prtconf -F (Return the device pathname of the console frame buffer)  
m64config -res 1152x900x76 -depth 8  
ls -l /dev/fbs/ffb0 (一个符号链接)  
/usr/sbin/ffbconfig -prconf -propt (当前设置1152x900x76x8)  
参看m64config(1M)、ffbconfig(1M)手册页  
9.6 Solaris下如何设置显示刷新率  
A: CERNET 华中地区网络中心 UNIX版 domyself 2001-08-16  
除了m64config(1M),还有一种办法,就是进入OBP状态设置分辨率、刷新率。进入  
OBP状态至少有两种方法  
# sync     show-displays  
这里可以看到当前的显示设备,如果你只有一个显示设备,那么这里有两个提示,选  
择a就选择了当前显示设备,选择q表示退出,你只能选择a。选择之后可以Ctrl-Y输  
入那个很长的设备路径全名。  
ok> dev  (用Ctrl-Y输入)  
选择并设置成当前结点,后面的words命令只处理当前结点,不接受指定  
ok> pwd  (验证当前路径是否正确)  
ok> words  
列出当前结点的方法名,分辨率和刷新率是作为方法提供的。比如你可能看到  
r1024x768x77x24  
r1152x900x76x8  
注意,数字前面有一个小写的'r',表示resolution。假设我们以前的设置是  
1152x900x76x8,现在想改成1024x768x77x24,用如下命令  
ok> setenv output-device screen:r1024x768x77x24  
ok> boot -r  
再次注意,"screen:"之后指定的是方法名,也就是说前面有那个小写的'r'。你用  
words看到什么就指定什么。自己估计显存大小,分辨率、刷新率、颜色深度是相互  
制约的。最好不要自己调节这些参数,很容易损坏显示设备。OBP状态下设置分辨率、  
刷新率的命令普遍描述如下  
ok> setenv output-device :  
上面screen是个别名,可以用devalias看到本来的设备路径全名,也就是  
show-displays看到的那个设备路径全名。指定设备路径全名也可以,如果你撑着了  
的话。  
ok> devalias  (检查设备别名)  
启动之后可以用如下命令检查当前设置  
# m64config -prconf | grep Current  
Current resolution setting: 1024x768x77  
Current depth: 24  
#  
警告:和调节PC机所配显示设备一样,这种调节具有破坏性,务必小心。对于高版本  
      的Solaris,建议使用m64config等工具调节显示刷新率,低版本Solaris才考  
      虑进入OBP状态设置。  
A: 水木清华 humvee  
x86/Solaris下可用kdmconfig  
_________________________________________________________________________________________________
10.   网卡相关问题  
10.1  如何在程序中获取本机MAC地址  
10.2  如何在Sun工作站上安装3块网卡  
10.3  如何在Solaris x86上安装网卡驱动  
10.4  Solaris 单网卡多IP(以太网卡别名)  
10.5  如何修改主机名(hostname)  
10.6  SPARC/Solaris 2.5/2.6/7/8下如何设置网卡100Mb全双工  
10.7  Unix/Linux/BSD如何对抗ARP欺骗攻击  
10.8   
10.9   
10.10  
10.11 x86/Solaris如何强制设定网卡速率  
10.12 Solaris/FreeBSD/Linux如何确定网卡Capability/Speed  
10.13  
10.14 traceroute是怎么实现的  
--------------------------------------------------------------------------  
10. 网卡相关问题  
10.1 如何在程序中获取本机MAC地址  
Q: 如何在C代码中获取本机MAC地址,我用strace跟踪ifconfig  
   ioctl(4, SIOCGIFHWADDR, 0xbffffb80)     = 0  
   ioctl(4, SIOCGIFADDR, 0xbffffb80)       = 0  
   ioctl(4, SIOCGIFBRDADDR, 0xbffffb80)    = 0  
   ioctl(4, SIOCGIFNETMASK, 0xbffffb80)    = 0  
D: Unix Programmer  
用gethostname()/gethostbyname()依赖于本机的域名解析系统,比如/etc/hosts文  
件、/etc/nsswitch.conf文件、/etc/resolv.conf文件。这样获取本机IP是不可靠的。  
如果/etc/hosts文件中没有指定本机IP,则依赖DNS是否配置了PTR资源记录。可靠的  
办法应该是strace ifconfig、truss ifconfig,实际就是照ifconfig的实现去获取  
本机IP。  
A: David Peter   
strace是Linux下的工具,由于HP-UX 10.20的ioctl不支持SIOCGIFHWADDR,可能需要  
DLPI接口或者针对/dev/lan0的NETSTAT ioctl,为了使用NETSTAT ioctl还需要重启  
动,而且HP不赞成继续使用NETSTAT ioctl,HP-UX 11.00不再支持。  
根据手头一个古老的工具,Digital Unix下ioctl支持SIOCRPHYSADDR。至于SGI上的  
IRIX,我想可能需要一个原始套接字,比如:  
s = socket( PF_RAW, SOCK_RAW, RAWPROTO_SNOOP )  
D: scz  2001-11-20 11:46  
SPARC/Solaris下只有root用户才可以ifconfig -a看到本机MAC地址,普通用户并不  
能这样做,但可以尝试在dmesg输出中查找,由于dmesg使用的数据有可能被破坏,这  
个办法并不可靠。  
"arp "可以看到本机MAC地址,使用的技术实际上就是前面编程演示的  
ioctl( s, SIOCGARP, &arpreq )  
此外还可以用如下命令获取本机MAC地址  
ndd /dev/arp arp_cache_report | grep MYADDR  
10.2 如何在Sun工作站上安装3块网卡  
Q: 我想在Sun工作站上安装3块网卡,怎么办  
A: Santosh  
请遵循如下步骤  
1) 在Sun工作站上增加网卡  
2) 用boot -r启动系统  
3) 观察启动信息,确认每块网卡都被识别出来,比如这种信息  
   PCI-device:
[email=network@1,1]network@1,1[/email]
, hme #0  
   SUNW,hme0 is /pci@1f,4000/network@1,1  
   实际中如果每块网卡都被识别出来,有hme0、hme1 和 hme2,当然1和2可能不是  
   这个名字。  
4) 到/etc目录下创建hostname.hme0、hostname.hme1 和 hostname.hme2。在每个文  
   件中分别指定IP地址,编辑/etc/hosts文件增加相应入口。  
5) 重启机器  
10.3 如何在Solaris x86上安装网卡驱动  
A: James Adkins   
不需要修改"pcn.conf"文件。开始我只是"touch /reconfigure",Solaris x86检测  
到了网卡,但是"ifconfig -a"的时候只有loopback接口,于是我尝试如下步骤:  
# drvconfig  
# devlinks  
# touch /reconfigure  
重启动后一切ok  
10.4 Solaris 单网卡多IP(以太网卡别名)  
Q: 对于Solaris 2.5.1来说,可以在一块物理网卡上配置多个IP地址  
A: Sun Microsystems 1998-03-31  
下面以lance ethernet (le0) 设备为例说明  
1) 编辑/etc/hosts文件  
128.195.10.31 myhost  
128.195.10.46 myhost2  
128.195.10.78 myhost3  
2) 创建/etc/hostname.le0:n文件,注意hostname.le0:0就是hostname.le0  
/etc/hostname.le0   (Contains name myhost)  
/etc/hostname.le0:1 (Contains name myhost2)  
/etc/hostname.le0:2 (Contains name myhost3)  
注意这种文件就一行内容,主机名。  
3) 如果想立即生效  
% ifconfig le0:1 up  
% ifconfig le0:1 129.153.76.72  
% ifconfig le0:1 down  
Q: Solaris 8下如何给一块以太网卡赋予多个IP地址?  
A: Vadim V. Kouevda   
ifconfig le0 plumb  
ifconfig le0 ether 0:1:2:3:4:5  
ifconfig le0:1 plumb  
ifconfig le0:1 ... up  
ifconfig le0:2 plumb  
ifconfig le0:2 ... up  
到/etc/init.d目录下修改IP地址、子网掩码等设置。  
D: scz   
有三个文件需要注意,/etc/rcS.d/S30rootusr.sh(/etc/init.d/rootusr)、  
/etc/rc2.d/S69inet(/etc/init.d/inetinit)和/etc/rc2.d/S72inetsvc  
(/etc/init.d/inetsvc)。  
Q: 如何在一块物理网卡上绑定多个IP地址  
A: Sun Microsystems 1997-10-27  
所谓虚拟网络接口指一个物理接口多个不同IP地址,Solaris允许一个物理网络接口  
对应多个逻辑接口,换句话说,即使只有一块网卡,也可以配置多个IP地址。参看  
ifconfig(1M)手册页。对于Solaris 2.x,可以在一块网卡上绑定256个不同IP地址。  
Sun OS 4.x(Solaris 1.x)不支持。  
/usr/sbin/ndd -get /dev/ip ip_addrs_per_if  
对于Solaris 2.6,通过ndd可以配置超过256(0-255)个IP地址。  
/usr/sbin/ndd -set /dev/ip ip_addrs_per_if 1-8192  
将这条命令增加到/etc/rc2.d/S69inet启动脚本中去。  
1) 编辑/etc/hosts文件(或者nis host map),为每个虚拟接口增加条目。别忘记修  
   改NIS、NIS+、DNS数据库。  
2) 为每个接口创建/etc/hostname.文件,比如/etc/hostname.le0:1、  
   hostname.le0:2、hostname.le0:3 ... le0:255。文件内容为单行IP地址或者主  
   机名。比如创建如下文件  
   /etc/hostname.le0:1  (不要使用le0:0,那就是le0)  
   /etc/hostname.le0:2  
   Solaris 2.5.1下最多1024个虚拟接口。每个文件内容是自己对应的虚拟接口IP地  
   址或者主机名。  
3) 如果使用了子网,应该在/etc/netmasks中增加  
   network_address  netmask  
   157.145.0.0  255.255.255.0  
4) 重启系统  
5) ifconfig -a验证之  
某些第三方应用程序此时可能会出问题。出于安全考虑,可以  
ndd -set /dev/ip ip_forwarding 0  
ndd -set /dev/ip ip_strict_dst_multihoming 1  
参看RFC1112 - >。  
如果因为配置虚拟接口出现不期望的路由,考虑手动"route delete"。可以增加一个  
启动脚本/etc/rc2.d/S99vif,用于完成这些任务。  
对于Solaris 2.6,可能还需要  
ndd -set /dev/ip ip_enable_group_ifs 0 (2.6下缺省是1,7下缺省是0)  
将这条命令增加到/etc/rc2.d/S69inet启动脚本中去。  
10.5 如何修改主机名(hostname)  
Q: Solaris 2.6下如何修改主机名(hostname)  
A: Herve Poussin   
需要修改如下文件  
/etc/hosts  
/etc/hostname.  
/etc/nodename  
/etc/net/*/hosts (3 files, man -s 7D ticotsord)  
如果你运行在VxVM下,则应该  
# vxdctl hostid   
# vxdctl init   
10.6 SPARC/Solaris 2.5/2.6/7/8下如何设置网卡100Mb全双工  
Q: 我从SPARC连接3Com交换机时,总是使用半双工,如何配置网卡强行使用100Mb全  
   双工  
A: Martin Scerri   
下列回答来自"Sun管理员FAQ 12.3",并且只适合于Solaris 2.5及其以后版本,  
Sun OS 4.x及其更早版本不支持hme接口。  
一般网卡可以和交换机自动协商使用100Mb全双工,如果协商失败,可能看到诸如  
"late collision"一类的消息,出现丢包甚至完全不能工作的现象。为了强行指定使  
用某一确定的工作模式,比如100Mb FD,可以用ndd做如下操作:  
# 指定操作hme0接口  
ndd -set /dev/hme instance 0  
# 关闭自动协商  
ndd -set /dev/hme adv_autoneg_cap  0  
# 打开100Mb FD支持  
ndd -set /dev/hme adv_100fdx_cap   1  
# 关闭100Mb HD支持  
ndd -set /dev/hme adv_100hdx_cap   0  
# 关闭10Mb FD支持  
ndd -set /dev/hme adv_10fdx_cap    0  
# 关闭10Mb HD支持  
ndd -set /dev/hme adv_10hdx_cap    0  
同样需要在对端(比如交换机)强行指定使用100Mb FD模式。  
注意:Fast ethernet hubs 总是使用100Mb HD模式  
      ethernet hubs 总是使用10Mb HD模式  
如果你想强行指定系统中所有hme网卡在启动时进入同一确定模式,可以在  
/etc/system文件中设置,下例表示进入100Mbit FD模式:  
set hme:hme_adv_autoneg_cap=0  
set hme:hme_adv_100fdx_cap=1  
set hme:hme_adv_100hdx_cap=0  
set hme:hme_adv_10hdx_cap=0  
set hme:hme_adv_10fdx_cap=0  
A: Andreas.Gouder   
你可以用如下命令获取当前设置  
# ndd -get /dev/hme link_mode  
0 半双工  
1 全双工  
# ndd -get /dev/hme link_status  
0 Link Down  
1 Link up  
# ndd -get /dev/hme link_speed  
0 10Mbps  
1 100Mbps  
10.7 Unix/Linux/BSD如何对抗ARP欺骗攻击  
Q: Solaris的静态ARP表项(arp -s)还是会被动态刷新,我只确认Linux/FreeBSD的静  
   态ARP表项不会被动态刷新,到底有没有稍微通用点的对抗ARP欺骗攻击的方法。  
A: scz   
下面以Solaris系统为例说明,其他系统大同小异。  
1) 建立静态ARP表  
/usr/bin/touch /etc/static_arp_entry  
/usr/bin/chown root:root /etc/static_arp_entry  
/usr/bin/chmod 600 /etc/static_arp_entry  
编辑/etc/static_arp_entry文件,输入类似内容  
192.168.8.90    00:00:00:11:11:11  
/usr/sbin/arp -s -f /etc/static_arp_entry  
可以在/etc/rc2.d/S69inet启动脚本中增加这条命令。参看arp(1M)、arp(7P)手册页  
了解更多细节。这种技术对系统影响不大,对网络影响较大,破坏了动态ARP解析过  
程。Solaris系统中,静态ARP表不会过期,必须用"arp -d"手动删除。但是,  
Solaris系统的静态ARP表项可以被动态刷新,仅仅依靠静态ARP表项并不能对抗ARP欺  
骗攻击,相反纵容了ARP欺骗攻击,因为虚假的静态ARP表项不会自动超时消失。当然,  
可以考虑利用cron机制补救之。(增加一个crontab)  
为了对抗ARP欺骗攻击,对于Solaris系统来说,应该结合"禁止相应网络接口做ARP解  
析"和"使用静态ARP表"的设置  
2) 禁止某个网络接口做ARP解析(对抗ARP欺骗攻击)  
"/sbin/ifconfig hme0 -arp"命令将禁止hme0接口做ARP解析,hme0接口不会发送/接  
收ARP报文。必须配合使用静态ARP表,否则无法完成正常网络通信。参看  
ifconfig(1M)了解更多细节。假设/etc/rc2.d/S69inet启动脚本中存在如下内容  
/sbin/ifconfig hme0 -arp  
/usr/sbin/arp -s -f /etc/static_arp_entry  
假设/etc/static_arp_entry文件内容如下  
192.168.8.90    00:00:00:11:11:11  
这里192.168.8.90是一台PWin98,也做静态ARP设置(因为对方不会响应ARP请求报文)  
arp -s 192.168.10.6 08-00-20-a8-2e-ac  
此时192.168.8.90与192.168.10.6可以正常通信,并且192.168.10.6不受ARP欺骗攻  
击的影响。事实上,绝大多数Unix/Linux/BSD操作系统,都可以结合"禁止相应网络  
接口做ARP解析"和"使用静态ARP表"的设置来对抗ARP欺骗攻击。对于Linux/FreeBSD  
系统,因为其静态ARP表项(arp -s)不会被动态刷新,所以不需要"禁止相应网络接口  
做ARP解析"即可对抗ARP欺骗攻击。  
10.11 x86/Solaris如何强制设定网卡速率  
Q: x86/Solaris,我如何强行指定网卡的工作状态为100Mbps full-duplex,ndd(1M)  
   不工作  
A: CERNET 水木清华 Unix版 inc 2001-10-11 20:29  
x86/Solaris下的网卡驱动不支持ndd(1M)设置网卡工作状态,要达到目的,唯一的办  
法是通过driver.conf(4)指定。x86/Solaris 8的iprb(7D)手册页建议使用  
ForceSpeedDuplex选项。对于其它驱动,参看如下例子  
vi /kernel/drv/iprb.conf   | grep ifspeed  
某些x86网卡驱动支持,某些不支持,这个办法同样适合于SPARC网卡驱动,虽然后者  
可以直接使用ndd(1M)。  
10.12 Solaris/FreeBSD/Linux如何确定网卡Capability/Speed  
A: 小四  2001-12-07 17:06  
Solaris  
# netstat -k hme0 | grep ifspeed  
# ndd -get /dev/hme link_mode  
0 半双工  
1 全双工  
# ndd -get /dev/hme link_status  
0 Link Down  
1 Link up  
# ndd -get /dev/hme link_speed  
0 10Mbps  
1 100Mbps  
FreeBSD用ifconfig就可以看到  
status: active        
traceroute(对于Windows系列是tracert)通过逐步增加TTL值的方法,发送常规IP分  
组来实现。第一次发送分组时TTL为1,第一个路由器接收到该分组之后将TTL值减1,  
结果为0,于是就丢弃该分组,并发回一个"TTL超时"的ICMP报文,该报文的源地址是  
这第一个路由器。紧接着发送一个TTL为2的分组。注意,traceroute发送常规的UDP  
报文到一个不用的UDP端口。当初考虑将路由跟踪的功能加入IP协议本身,定义一个  
"路由跟踪"选项,路由器处理带有该选项的IP包时立即发回一个跟踪报文到源站点。  
然而这种做法还停留在实验室阶段,因为这需要改变所有已经存在的路由器,而且在  
某种程度上与端到端原则相违背。  
1) 传统的Unix实现是UDP+ICMP  
2) 其实从原理上TCP+ICMP也是可以的,某些Unix系统采用了这种实现  
3) Windows另有一种实现,Icmp Echo Request+ICMP  
_________________________________________________________________________________________________
11.   package相关问题  
11.1  Solaris下如何将二进制软件包安装到指定目标路径下  
11.2  Solaris下如何自己定制二进制安装包  
11.3  如何恢复/usr/bin/su的缺省安装属性  
11.4  如何获知指定包与其他包之间的依赖关系  
11.5  Linux中如何知道ifconfig属于哪个包  
11.6  Solaris下如何知道某包中有哪些文件  
--------------------------------------------------------------------------  
11. package相关问题  
11.1 Solaris下如何将二进制软件包安装到指定目标路径下  
Q: pkgadd无法指定目标路径,而我不想使用缺省安装路径/usr/local  
A: lisuit@水木清华 2002-01-19 14:49  
pkgadd -R  ...  
11.2 Solaris下如何自己定制二进制安装包  
A: deepin  & scz   
[root@ /tmp/tools]> mkdir srcroot  
[root@ /tmp/tools]> cp -p /usr/ccs/bin/as srcroot   cp -p /usr/ccs/bin/make srcroot  
[root@ /tmp/tools]> cp -p /usr/ccs/lib/cpp srcroot  
[root@ /tmp/tools]> ls -lR srcroot  
-rwxr-xr-x   1 bin      bin       342072 1999   1月 12 as*  
-rwxr-xr-x   1 bin      bin        91344 1998   4月 27 cpp*  
-rwxr-xr-x   1 bin      bin       273196 1998   4月 23 make*  
[root@ /tmp/tools]> cd srcroot  
[root@ /tmp/tools/srcroot]> find . -print | pkgproto > ../prototype  
[root@ /tmp/tools/srcroot]> cd ..  
[root@ /tmp/tools]> more prototype  
f none cpp 0755 bin bin  
f none as 0755 bin bin  
f none make 0755 bin bin  
[root@ /tmp/tools]> vi prototype   vi pkginfo  
PKG="Scz"  
NAME="Scz Package Cool Tools"  
VERSION="2000-01-09 14:53"  
CATEGORY="application"  
PSTAMP="小四"  
CLASSES="none"  
ARCH="Solaris 2.7 For SPARC"  
VENDOR="NSFocus"  
BASEDIR="/tmp/tools/opt/"  
EMAIL="
scz@nsfocus.com
"  
[root@ /tmp/tools]> pkgmk -o -f ./prototype -b /tmp/tools/srcroot  
[root@ /tmp/tools]> pkgtrans -s /var/spool/pkg /tmp/tools/SczPkg Scz  
[root@ /tmp/tools]> rm -rf /var/spool/pkg/Scz  
[root@ /tmp/tools]> pkgadd -d SczPkg  
[root@ /tmp/tools]> ls -lR opt  
-rwxr-xr-x   1 bin      bin       342072 1999   1月 12 as*  
-rwxr-xr-x   1 bin      bin        91344 1998   4月 27 cpp*  
-rwxr-xr-x   1 bin      bin       273196 1998   4月 23 make*  
[root@ /tmp/tools]> pkginfo -l Scz  
[root@ /tmp/tools]> pkgrm Scz  
[root@ /tmp/tools]> rm SczPkg  
11.3 如何恢复/usr/bin/su的缺省安装属性  
Q: 我怀疑/usr/bin/su被修改过了,如何证实呢  
A: John D Groenveld   
$ pkgchk -l -p /usr/bin/su  
11.4 如何获知指定包与其他包之间的依赖关系  
A: Vitaly Filatov   
详细信息查看 /var/sadm/pkg//install/depend 文件,这里指明了该包的  
三个特性  
    P 安装前必须已经存在的包  
    I 与自己不兼容的包  
    R 依赖自己的其他包  
11.5 Linux中如何知道ifconfig属于哪个包  
A:  
# rpm -qif /sbin/ifconfig   2001-12-10 21:39  
1) 已经安装了的包,对/var/sadm/install/contents文件做grep操作  
# grep SUNWcsd /var/sadm/install/contents  
       ~~~~~~~ 包名  
2) 尚未安装的包,先伪安装,然后检查pkgmap文件  
# pkgadd -s /var/spool/pkg -d less-340-sol7-sparc-local  
# cd /var/spool/pkg/GNUless  
# grep BASEDIR pkginfo   
第一种办法是读取/proc接口提供的信息  
--------------------------------------------------------------------------  
/* gcc -Wall -O3 -o getpid getpid.c */  
#include   
#include   
#include   
#include   
#include   
#include   
#include   
#include   
#include   
static pid_t getpidbyname ( char * name, pid_t skipit )  
{  
    DIR *           dirHandle;  /* 目录句柄   */  
    struct dirent * dirEntry;   /* 单个目录项 */  
    prpsinfo_t      prp;  
    int             fd;  
    pid_t           pid = -1;  
    if ( ( dirHandle = opendir( "/proc" ) ) == NULL )  
    {  
        return( -1 );  
    }  
    chdir( "/proc" );  /* 下面使用相对路径打开文件,所以必须进入/proc */  
    while ( ( dirEntry = readdir( dirHandle ) ) != NULL )  
    {  
        if ( dirEntry->d_name[0] != '.' )  
        {  
            /* fprintf( stderr, "%sn", dirEntry->d_name ); */  
            if ( ( fd = open( dirEntry->d_name, O_RDONLY ) ) != -1 )  
            {  
                if ( ioctl( fd, PIOCPSINFO, &prp ) != -1 )  
                {  
                    /* fprintf( stderr, "%sn", prp.pr_fname ); */  
                    if ( !strcmp( prp.pr_fname, name ) )  /* 这里是相对路径,而且  
不带参数 */  
                    {  
                        pid = ( pid_t )atoi( dirEntry->d_name );  
                        if ( skipit != -1 && pid == skipit )  /* -1做为无效pid对  
待 */  
                        {  
                            pid = -1;  
                        }  
                        else  /* 找到匹配 */  
                        {  
                            close( fd );  
                            break;  /* 跳出while循环 */  
                        }  
                    }  
                }  
                close( fd );  
            }  
        }  
    }  /* end of while */  
    closedir( dirHandle );  
    return( pid );  
}  /* end of getpidbyname */  
static void usage ( char * arg )  
{  
    fprintf( stderr, " Usage: %s n", arg );  
    exit( EXIT_FAILURE );  
}  /* end of usage */  
int main ( int argc, char * argv[] )  
{  
    pid_t pid;  
    if ( argc != 2 )  
    {  
        usage( argv[0] );  
    }  
    pid = getpidbyname( argv[1], -1 );  
    if ( pid != -1 )  
    {  
        fprintf( stderr, "[ %s ] is: n", argv[1], ( unsigned int )pid );  
        exit( EXIT_SUCCESS );  
    }  
    exit( EXIT_FAILURE );  
}  /* end of main */  
--------------------------------------------------------------------------  
这种技术要求运行者拥有root权限,否则无法有效获取非自己拥有的进程PID。注意  
下面的演示  
# ps -f -p 223  
UID   PID  PPID  C    STIME TTY      TIME CMD  
root   223     1  0   3月 09 ?        0:00 /usr/sbin/vold  
# ./getpid /usr/sbin/vold   
当然你可以自己修改、增强程序,使之匹配各种命令行指定,我就不替你做了。上述  
程序在32-bit kernel的Solaris 2.6和64-bit kernel的Solaris 7上均测试通过。  
D: microcat   
在介绍第二种办法之前,先看一下microcat提供的这个程序  
--------------------------------------------------------------------------  
/*  
* gcc -Wall -DSOLARIS=6 -O3 -o listpid listpid.c -lkvm  
*  
* /opt/SUNWspro/SC5.0/bin/cc -xarch=v9 -DSOLARIS=7 -O -o listpid listpid.c -lkv  
m  
*/  
#include   
#include   
#include   
#include   
#include   
int main ( int argc, char * argv[] )  
{  
    kvm_t *       kd;  
    struct proc * p;  
    struct pid    pid;  
    if ( ( kd = kvm_open( NULL, NULL, NULL, O_RDONLY, NULL ) ) == NULL )  
    {  
        perror( "kvm_open" );  
        exit( EXIT_FAILURE );  
    }  
    while ( ( p = kvm_nextproc( kd ) ) )  /* 遍历P区 */  
    {  
#if SOLARIS == 7  
        if ( kvm_kread( kd, ( uintptr_t )p->p_pidp, &pid, sizeof( pid ) ) p_pidp, ( char * )&pid, sizeof(  
pid ) )   
第二种办法是使用kvm_*()函数  
--------------------------------------------------------------------------  
#define _KMEMUSER  /* 必须定义这个宏 */  
#include   
#include   
#include   
#include   
#include   
#include   
/*  
static void argv_free ( char ** argv )  
{  
    size_t i;  
    for ( i = 0; argv != NULL; i++ )  
    {  
        free( argv );  
        argv = NULL;  
    }  
    free( argv );  
}  
*/  
static pid_t getpidbyname ( char * name, pid_t skipit )  
{  
    kvm_t *       kd;  
    int           error;  
    char **       argv   = NULL;  
    char *        p_name = NULL;  
    pid_t         pid    = -1;  
    char          expbuf[256];  
    char          regexp_str[256];  
    struct user * cur_user;  
    struct proc * cur_proc;  
    struct pid    p;  
    sprintf( regexp_str, "^.*%s$", name );  
    if ( compile( regexp_str, expbuf, expbuf + 256 ) == NULL )  /* 正则表达式 */  
    {  
        perror( "compile" );  
        return( -1 );  
    }  
    if ( ( kd = kvm_open( NULL, NULL, NULL, O_RDONLY, NULL ) ) == NULL )  
    {  
        perror( "kvm_open" );  
        return( -1 );  
    }  
    while ( ( cur_proc = kvm_nextproc( kd ) ) )  /* 遍历P区 */  
    {  
#if SOLARIS == 7  
        if ( kvm_kread( kd, ( uintptr_t )cur_proc->p_pidp, &p, sizeof( p ) ) p_pidp, ( char * )&p, siz  
eof( p ) ) n", cur_user->u_comm, ( unsigne  
d int )pid );  
             *  
             * 比如in.telnetd、syslogd、bash、login  
             */  
            if ( error == -1 )  /* 失败,比如argv[]已经被进程自己修改过 */  
            {  
                if ( cur_user->u_comm[0] != '' )  
                {  
                    p_name = cur_user->u_comm;  /* 从另外一个地方获取信息 */  
                }  
            }  
            else  /* 成功 */  
            {  
                /*  
                 * fprintf( stderr, "[ %s ] is: n", argv[0], ( unsigned int  
)pid );  
                 *  
                 * 比如-bash、login、in.telnetd、/usr/sbin/syslogd  
                 */  
                p_name = argv[0];  
            }  
        }  
        if ( p_name )  
        {  
            if ( ( strcmp( p_name, name ) == 0 ) || step( p_name, expbuf ) )  
            {  
                if ( skipit != -1 && pid == skipit )  /* -1做为无效pid对待 */  
                {  
                    pid = -1;  
                }  
                else  /* 找到匹配,返回pid */  
                {  
                    break;  /* 跳出while循环 */  
                }  
            }  
        }  
        if ( argv != NULL )  
        {  
            /* argv_free( argv ); */  
            free( argv );  
            argv = NULL;  
        }  
        p_name = NULL;  /* 必须增加这条,否则流程有问题 */  
    }  /* end of while */  
    if ( argv != NULL )  
    {  
        /* argv_free( argv ); */  
        free( argv );  
        argv = NULL;  
    }  
    kvm_close( kd );  
    return( pid );  
}  /* end of getpidbyname */  
static void usage ( char * arg )  
{  
    fprintf( stderr, " Usage: %s n", arg );  
    exit( EXIT_FAILURE );  
}  /* end of usage */  
int main ( int argc, char * argv[] )  
{  
    pid_t pid;  
    if ( argc != 2 )  
    {  
        usage( argv[0] );  
    }  
    pid = getpidbyname( argv[1], -1 );  
    if ( pid != -1 )  
    {  
        fprintf( stderr, "[ %s ] is: n", argv[1], ( unsigned int )pid );  
        exit( EXIT_SUCCESS );  
    }  
    exit( EXIT_FAILURE );  
}  /* end of main */  
--------------------------------------------------------------------------  
这个程序同样必须以root身份运行,在SPARC/Solaris 2.6/7上测试通过  
13.4 Solaris 7/8下ps输出中的问号  
Q: 比如ps -el的输出中有很多问号,可我觉得它们应该有一个确定的值  
A: Michael Shapiro   
   有些时候ps(1)输出的单行过于长了,为了输出美观,某些列的值用问号代替,尤  
   其64-bit内核下ADDR列。可以用-o参数指定要显示的列,比如  
   # ps -o pid,tty,addr,wchan,fname -p $$  
   PID TT                  ADDR            WCHAN COMMAND  
   2602 pts/4        30000a154b8      30000a15578 bash  
   # ps -e -o pid,tty,addr,wchan,fname  
13.7 给定一个PID,如何知道它对应一个运行中的进程  
A: Andrew Gierth   
这个回答来自著名的>,由Andrew Gierth负责维  
护,其它细节请参看原文。  
kill( pid, 0 ),此时有四种可能的返回值  
1) kill()返回0  
    意味着指定PID的确对应着一个运行中的进程,系统允许你向该进程发送信号。  
    至于该进程能否是zombie process(僵尸进程),是系统相关的。  
2) kill()返回-1,errno == ESRCH  
    指定PID并不对应一个运行中的进程,或者权限不够无法完成判断。某些系统上,  
    如果对应进程是僵尸进程时,也如此返回。  
3) kill()返回-1,errno == EPERM  
    系统不允许你kill指定进程,进程存在(可能是zombie),权限不够。  
4) kill()返回-1,errno是其它值  
    你麻烦来了(嘿嘿)  
最有用的技术,假设成功表示进程存在,EPERM失败也表示进程存在,其它失败表示  
指定PID不对应一个运行中的进程。  
此外如果系统支持proc伪文件系统,检查/proc/是否存在,存在表明指定PID对  
应运行中的进程。  
13.8 Unix/Linux编程中所谓"僵尸进程"指什么  
Q: Unix/Linux编程中所谓"僵尸进程"指什么,什么情况下会产生僵尸进程,如何杀  
   掉僵尸进程。  
A: 在fork()/execve()过程中,假设子进程结束时父进程仍存在,而父进程fork()之  
   前既没安装SIGCHLD信号处理函数调用waitpid()等待子进程结束,又没有显式忽  
   略该信号,则子进程成为僵尸进程,无法正常结束,此时即使是root身份kill -9  
   也不能杀死僵尸进程。补救办法是杀死僵尸进程的父进程(僵尸进程的父进程必然  
   存在),僵尸进程成为"孤儿进程",过继给1号进程init,init始终会负责清理僵  
   尸进程。  
13.9 x86/FreeBSD 4.3-RELEASE的ptrace(2)手册页  
A: scz   
下面来看一个简单的ptrace(2)演示,x86/FreeBSD 4.3-RELEASE  
--------------------------------------------------------------------------  
/*  
* gcc -Wall -pipe -O3 -o target target.c  
*/  
#include   
#include   
#include   
#include   
#include   
int main ( int argc, char * argv[] )  
{  
    write( STDERR_FILENO, "Hello worldn", 12 );  
    return( EXIT_SUCCESS );  
}  /* end of main */  
--------------------------------------------------------------------------  
--------------------------------------------------------------------------  
/*  
* gcc -Wall -pipe -O3 -o ptracetest ptracetest.c  
*/  
#include   
#include   
#include   
#include   
#include   
#include   
#include   
#include   
#include   
int main ( int argc, char * argv[] )  
{  
    pid_t p;  
    p = fork();  
    if ( p < 0 )  
    {  
        perror( "fork error" );  
        exit( EXIT_FAILURE );  
    }  
    else if ( p == 0 )  
    {  
        /*  
         * 子进程  
         */  
        errno = 0;  
        ptrace( PT_TRACE_ME, 0, 0, 0 );  
        if ( errno != 0 )  
        {  
            perror( "child process ptrace error" );  
            exit( EXIT_FAILURE );  
        }  
        else  
        {  
            char * name[2];  
            name[0] = "./target";  
            name[1] = NULL;  
            /*  
             * 切换进程映像时停止执行  
  &

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/1102/showart_11633.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP