- 论坛徽章:
- 0
|
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 |
|