免费注册 查看新帖 |

Chinaunix

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

arping代码分析 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-04-02 10:23 |只看该作者 |倒序浏览
linux的arping,还有一点问题(见分析注释),希望大家指教

  1. /*
  2. * arping.c
  3. *
  4. *                This program is free software; you can redistribute it and/or
  5. *                modify it under the terms of the GNU General Public License
  6. *                as published by the Free Software Foundation; either version
  7. *                2 of the License, or (at your option) any later version.
  8. *
  9. * Authors:        Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>;
  10. */

  11. #include <stdlib.h>;
  12. #include <sys/param.h>;
  13. #include <sys/socket.h>;
  14. #include <linux/sockios.h>;
  15. #include <sys/file.h>;
  16. #include <sys/time.h>;
  17. #include <sys/signal.h>;
  18. #include <sys/ioctl.h>;
  19. #include <linux/if.h>;
  20. #include <linux/if_arp.h>;
  21. #include <sys/uio.h>;

  22. #include <netdb.h>;
  23. #include <unistd.h>;
  24. #include <stdio.h>;
  25. #include <ctype.h>;
  26. #include <errno.h>;
  27. #include <string.h>;
  28. #include <netinet/in.h>;
  29. #include <arpa/inet.h>;

  30. #include "SNAPSHOT.h"

  31. static void usage(void) __attribute__((noreturn));

  32. int quit_on_reply=0;
  33. char *device="eth0";
  34. int ifindex;
  35. char *source;
  36. struct in_addr src, dst;
  37. char *target;
  38. int dad, unsolicited, advert;
  39. int quiet;
  40. int count=-1;
  41. int timeout;
  42. int unicasting;
  43. int s;
  44. int broadcast_only;

  45. struct sockaddr_ll me;
  46. struct sockaddr_ll he;

  47. struct timeval start, last;

  48. int sent, brd_sent;
  49. int received, brd_recv, req_recv;

  50. #define MS_TDIFF(tv1,tv2) ( ((tv1).tv_sec-(tv2).tv_sec)*1000 + \
  51.                            ((tv1).tv_usec-(tv2).tv_usec)/1000 )

  52. void usage(void)
  53. {
  54.         fprintf(stderr,
  55.                 "Usage: arping [-fqbDUAV] [-c count] [-w timeout] [-I device] [-s source] destination\n"
  56.                 "  -f : quit on first reply\n"
  57.                 "  -q : be quiet\n"
  58.                 "  -b : keep broadcasting, don't go unicast\n"
  59.                 "  -D : duplicate address detection mode\n"
  60.                 "  -U : Unsolicited ARP mode, update your neighbours\n"
  61.                 "  -A : ARP answer mode, update your neighbours\n"
  62.                 "  -V : print version and exit\n"
  63.                 "  -c count : how many packets to send\n"
  64.                 "  -w timeout : how long to wait for a reply\n"
  65.                 "  -I device : which ethernet device to use (eth0)\n"
  66.                 "  -s source : source ip address\n"
  67.                 "  destination : ask for what ip address\n"
  68.                 );
  69.         exit(2);
  70. }

  71. void set_signal(int signo, void (*handler)(void))
  72. {
  73.         struct sigaction sa;

  74.         memset(&sa, 0, sizeof(sa));
  75.         sa.sa_handler = (void (*)(int))handler;
  76.         sa.sa_flags = SA_RESTART;
  77.         sigaction(signo, &sa, NULL);
  78. }

  79. int send_pack(int s, struct in_addr src, struct in_addr dst,
  80.               struct sockaddr_ll *ME, struct sockaddr_ll *HE)
  81. {
  82.         int err;
  83.         struct timeval now;
  84.         unsigned char buf[256];
  85.         struct arphdr *ah = (struct arphdr*)buf;
  86.         unsigned char *p = (unsigned char *)(ah+1);
  87.        
  88.         ah->;ar_hrd = htons(ME->;sll_hatype);        /* 硬件地址类型*/
  89.         if (ah->;ar_hrd == htons(ARPHRD_FDDI))
  90.                 ah->;ar_hrd = htons(ARPHRD_ETHER);
  91.         ah->;ar_pro = htons(ETH_P_IP);                /* 协议地址类型   */
  92.         ah->;ar_hln = ME->;sll_halen;                /* 硬件地址长度   */
  93.         ah->;ar_pln = 4;                                /* 协议地址长度 */
  94.         ah->;ar_op  = advert ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST);/* 操作类型*/

  95.         memcpy(p, &ME->;sll_addr, ah->;ar_hln);                       /* 发送者硬件地址*/
  96.         p+=ME->;sll_halen;        /*以太网为6*/

  97.         memcpy(p, &src, 4);                /* 发送者IP */
  98.         p+=4;
  99.         /* 目的硬件地址*/
  100.         if (advert)
  101.                 memcpy(p, &ME->;sll_addr, ah->;ar_hln);
  102.         else
  103.                 memcpy(p, &HE->;sll_addr, ah->;ar_hln);
  104.         p+=ah->;ar_hln;

  105.         memcpy(p, &dst, 4);                /* 目的IP地址*/
  106.         p+=4;

  107.         gettimeofday(&now, NULL);
  108.         err = sendto(s, buf, p-buf, 0, (struct sockaddr*)HE, sizeof(*HE));
  109.         if (err == p-buf) {
  110.                 last = now;
  111.                 sent++;
  112.                 if (!unicasting)
  113.                         brd_sent++;
  114.         }
  115.         return err;
  116. }

  117. void finish(void)
  118. {
  119.         if (!quiet) {
  120.                 printf("Sent %d probes (%d broadcast(s))\n", sent, brd_sent);
  121.                 printf("Received %d response(s)", received);
  122.                 if (brd_recv || req_recv) {
  123.                         printf(" (");
  124.                         if (req_recv)
  125.                                 printf("%d request(s)", req_recv);
  126.                         if (brd_recv)
  127.                                 printf("%s%d broadcast(s)",
  128.                                        req_recv ? ", " : "",
  129.                                        brd_recv);
  130.                         printf(")");
  131.                 }
  132.                 printf("\n");
  133.                 fflush(stdout);
  134.         }
  135.         if (dad)
  136.                 exit(!!received);
  137.         if (unsolicited)
  138.                 exit(0);
  139.         exit(!received);
  140. }

  141. void catcher(void)
  142. {
  143.         /*这个函数的主要作用是调用send_pack发送一次arp请求*/
  144.         struct timeval tv;

  145.         gettimeofday(&tv, NULL);

  146.         if (start.tv_sec==0)
  147.                 start = tv;

  148.         if (count-- == 0 || (timeout && MS_TDIFF(tv,start) >; timeout*1000 + 500))
  149.                 finish();

  150.         if (last.tv_sec==0 || MS_TDIFF(tv,last) >; 500) {
  151.                 send_pack(s, src, dst, &me, &he);
  152.                 if (count == 0 && unsolicited)
  153.                         finish();
  154.         }
  155.         alarm(1);        /*每秒放松一个包*/
  156. }

  157. void print_hex(unsigned char *p, int len)
  158. {
  159.         int i;
  160.         /*打印MAC地址*/
  161.         for (i=0; i<len; i++) {
  162.                 printf("%02X", p[i]);
  163.                 if (i != len-1)
  164.                         printf(":");
  165.         }
  166. }
  167. /*数据包分析主程序.
  168. 把ARP 请求和答复的数据包格式画在这里,希望对理解下面的数据包分析有帮助

  169.                              |---------------28 bytes arp request/reply-----------------------------|       
  170. |--------ethernet header----|
  171. _____________________________________________________________________________________________________
  172. |ethernet | ethernet| frame|hardware|protocol|hardware|protocol|op|sender  |sender|target  |target|
  173. |dest addr|src addr | type| type   |type    | length |length  |  |eth addr| IP   |eth addr| IP    |
  174. -----------------------------------------------------------------------------------------------------  
  175.   6 types    6        2      2        2         1        1      2     6       4       6        4
  176. */
  177. int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
  178. {
  179.         struct timeval tv;
  180.         struct arphdr *ah = (struct arphdr*)buf;
  181.         unsigned char *p = (unsigned char *)(ah+1);
  182.         struct in_addr src_ip, dst_ip;

  183.         gettimeofday(&tv, NULL);

  184.         /* Filter out wild packets */
  185.         if (FROM->;sll_pkttype != PACKET_HOST &&
  186.             FROM->;sll_pkttype != PACKET_BROADCAST &&
  187.             FROM->;sll_pkttype != PACKET_MULTICAST)
  188.                 return 0;
  189.         /*到这里pkttype为HOST||BROADCAST||MULTICAST*/
  190.        
  191.         /* Only these types are recognised */
  192.         /*只要ARP request and reply*/
  193.         if (ah->;ar_op != htons(ARPOP_REQUEST) &&
  194.             ah->;ar_op != htons(ARPOP_REPLY))
  195.                 return 0;

  196.         /* ARPHRD check and this darned FDDI hack here :-( */
  197.         if (ah->;ar_hrd != htons(FROM->;sll_hatype) &&
  198.             (FROM->;sll_hatype != ARPHRD_FDDI || ah->;ar_hrd != htons(ARPHRD_ETHER)))
  199.                 return 0;

  200.         /* Protocol must be IP. */
  201.         if (ah->;ar_pro != htons(ETH_P_IP))
  202.                 return 0;
  203.         if (ah->;ar_pln != 4)
  204.                 return 0;
  205.         if (ah->;ar_hln != me.sll_halen)
  206.                 return 0;
  207.         if (len < sizeof(*ah) + 2*(4 + ah->;ar_hln))
  208.                 return 0;
  209.         /*src_ip:对方的IP
  210.           det_ip:我的IP*/
  211.         memcpy(&src_ip, p+ah->;ar_hln, 4);
  212.         memcpy(&dst_ip, p+ah->;ar_hln+4+ah->;ar_hln, 4);
  213.         if (!dad) {
  214.                 if (src_ip.s_addr != dst.s_addr)
  215.                         return 0;
  216.                 if (src.s_addr != dst_ip.s_addr)
  217.                         return 0;
  218.                 if (memcmp(p+ah->;ar_hln+4, &me.sll_addr, ah->;ar_hln))
  219.                         return 0;
  220.         } else {
  221.         /*一般是执行这里,被理上面那段*/
  222.                 /* DAD packet was:
  223.                    src_ip = 0 (or some src)
  224.                    src_hw = ME
  225.                    dst_ip = tested address
  226.                    dst_hw = <unspec>;

  227.                    We fail, if receive request/reply with:
  228.                    src_ip = tested_address
  229.                    src_hw != ME
  230.                    if src_ip in request was not zero, check
  231.                    also that it matches to dst_ip, otherwise
  232.                    dst_ip/dst_hw do not matter.
  233.                  */
  234.                  /*dst.s_addr是我们发送请求是置的对方的IP,当然要等于对方发来的包的src_ip啦*/
  235.                 if (src_ip.s_addr != dst.s_addr)
  236.                         return 0;
  237.                 if (memcmp(p, &me.sll_addr, me.sll_halen) == 0)
  238.                         return 0;
  239.                 /*同理,src.s_addr是我们发包是置的自己的IP,要等于对方回复包的目的地址*/
  240.                 if (src.s_addr && src.s_addr != dst_ip.s_addr)
  241.                         return 0;
  242.         }
  243.         if (!quiet) {
  244.         /*显示一些答复的信息,不是重点*/
  245.                 int s_printed = 0;
  246.                 printf("%s ", FROM->;sll_pkttype==PACKET_HOST ? "Unicast" : "Broadcast");
  247.                 printf("%s from ", ah->;ar_op == htons(ARPOP_REPLY) ? "reply" : "request");
  248.                 printf("%s [", inet_ntoa(src_ip));
  249.                 print_hex(p, ah->;ar_hln);
  250.                 printf("] ");
  251.                 if (dst_ip.s_addr != src.s_addr) {
  252.                         printf("for %s ", inet_ntoa(dst_ip));
  253.                         s_printed = 1;
  254.                 }
  255.                 if (memcmp(p+ah->;ar_hln+4, me.sll_addr, ah->;ar_hln)) {
  256.                         if (!s_printed)
  257.                                 printf("for ");
  258.                         printf("[");
  259.                         print_hex(p+ah->;ar_hln+4, ah->;ar_hln);
  260.                         printf("]");
  261.                 }
  262.                 if (last.tv_sec) {
  263.                         long usecs = (tv.tv_sec-last.tv_sec) * 1000000 +
  264.                                 tv.tv_usec-last.tv_usec;
  265.                         long msecs = (usecs+500)/1000;
  266.                         usecs -= msecs*1000 - 500;
  267.                         printf(" %ld.%03ldms\n", msecs, usecs);
  268.                 } else {
  269.                         printf(" UNSOLICITED?\n");
  270.                 }
  271.                 fflush(stdout);
  272.         }
  273.         received++;
  274.         if (FROM->;sll_pkttype != PACKET_HOST)
  275.                 brd_recv++;
  276.         if (ah->;ar_op == htons(ARPOP_REQUEST))
  277.                 req_recv++;
  278.         if (quit_on_reply)
  279.                 finish();
  280.         if(!broadcast_only) {
  281.                 memcpy(he.sll_addr, p, me.sll_halen);
  282.                 unicasting=1;
  283.         }
  284.         return 1;
  285. }

  286. int
  287. main(int argc, char **argv)
  288. {
  289.         int socket_errno;
  290.         int ch;
  291.         uid_t uid = getuid();
  292.         /*取得一个packet socket.
  293.         int packet_sock=socket(PF_PACKET,int sock_type,int protocol);
  294.         其中sock_type有两种:
  295.             1.SOCK_RAW,使用类型的套接子,那么当你向设备写数据时,要提供physical layer
  296.         header.当从设备读数据时,得到的数据是含有physical layer header的
  297.             2.SOCK_DGRAM.这种类型的套接字使用在相对高层.当数据传送给用户之前,physical layer
  298.             header已经去掉了(可能说的不合适,这是一个解封装的过程)*/
  299.         s = socket(PF_PACKET, SOCK_DGRAM, 0);
  300.         socket_errno = errno;
  301.         /*这个setuid没有什么用,因为arping没有setuid(我的系统是Mandrake 10)*/
  302.         setuid(uid);

  303.         while ((ch = getopt(argc, argv, "h?bfDUAqc:w:s:I:V")) != EOF) {
  304.                 switch(ch) {
  305.                 case 'b':
  306.                         broadcast_only=1;
  307.                         break;
  308.                 /*duplicate address dection mode对这个参数一直不明白.man page里说see rfc2131.4.4.1
  309.                 但rfc2131里好像没有这一节.好在这不是重点.大家有理解的请告诉我吧*/
  310.                 case 'D':
  311.                         dad++;
  312.                         quit_on_reply=1;
  313.                         break;
  314.                 case 'U':
  315.                         unsolicited++;
  316.                         break;
  317.                 case 'A':
  318.                         advert++;
  319.                         unsolicited++;
  320.                         break;
  321.                 case 'q':
  322.                         quiet++;
  323.                         break;
  324.                 case 'c':
  325.                         count = atoi(optarg);
  326.                         break;
  327.                 case 'w':
  328.                         timeout = atoi(optarg);
  329.                         break;
  330.                 case 'I':
  331.                         device = optarg;
  332.                         break;
  333.                 case 'f':
  334.                         quit_on_reply=1;
  335.                         break;
  336.                 case 's':
  337.                         source = optarg;
  338.                         break;
  339.                 case 'V':
  340.                         printf("arping utility, iputils-ss%s\n", SNAPSHOT);
  341.                         exit(0);
  342.                 case 'h':
  343.                 case '?':
  344.                 default:
  345.                         usage();
  346.                 }
  347.         }
  348.         argc -= optind;
  349.         argv += optind;

  350.         if (argc != 1)
  351.                 usage();

  352.         target = *argv;

  353.         if (device == NULL) {
  354.                 fprintf(stderr, "arping: device (option -I) is required\n");
  355.                 usage();
  356.         }

  357.         if (s < 0) {
  358.                 errno = socket_errno;
  359.                 perror("arping: socket");
  360.                 exit(2);
  361.         }

  362.         if (1) {
  363.                 struct ifreq ifr;
  364.                 memset(&ifr, 0, sizeof(ifr));
  365.                 strncpy(ifr.ifr_name, device, IFNAMSIZ-1);
  366.                 if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
  367.                         fprintf(stderr, "arping: unknown iface %s\n", device);
  368.                         exit(2);
  369.                 }
  370.                 ifindex = ifr.ifr_ifindex;

  371.                 if (ioctl(s, SIOCGIFFLAGS, (char*)&ifr)) {
  372.                         perror("ioctl(SIOCGIFFLAGS)");
  373.                         exit(2);
  374.                 }
  375.                 /*设备当然是要up的想要bring up eth0 可以/etc/sysconfig/network-scripts/ifup eth0*/
  376.                 if (!(ifr.ifr_flags&IFF_UP)) {
  377.                         if (!quiet)
  378.                                 printf("Interface \"%s\" is down\n", device);
  379.                         exit(2);
  380.                 }
  381.                 if (ifr.ifr_flags&(IFF_NOARP|IFF_LOOPBACK)) {
  382.                         if (!quiet)
  383.                                 printf("Interface \"%s\" is not ARPable\n", device);
  384.                         exit(dad?0:2);
  385.                 }
  386.         }
  387.         /*下面处理用户输入的目的地址,是11.22.33.44还是www.host.com?*/
  388.         if (inet_aton(target, &dst) != 1) {
  389.                 /*看来是www.host.com,那我们得到他的信息byname*/
  390.                 struct hostent *hp;
  391.                 hp = gethostbyname2(target, AF_INET);
  392.                 if (!hp) {
  393.                         fprintf(stderr, "arping: unknown host %s\n", target);
  394.                         exit(2);
  395.                 }
  396.                 /*要的是他的IP地址的binary representation*/
  397.                 memcpy(&dst, hp->;h_addr, 4);
  398.         }

  399.         if (source && inet_aton(source, &src) != 1) {
  400.                 fprintf(stderr, "arping: invalid source %s\n", source);
  401.                 exit(2);
  402.         }

  403.         if (!dad && unsolicited && src.s_addr == 0)
  404.                 src = dst;
  405.         /*下面这一大段确实有用么?好像唯一有用功是这一句  src = saddr.sin_addr;  */
  406.         if (!dad || src.s_addr)
  407.         {
  408.                 struct sockaddr_in saddr;
  409.                 int probe_fd = socket(AF_INET, SOCK_DGRAM, 0);

  410.                 if (probe_fd < 0)
  411.                 {
  412.                         perror("socket");
  413.                         exit(2);
  414.                 }
  415.                 if (device)
  416.                 {
  417.                         /*bind这个socket to
  418.                         "device".操作的结果是只有那个设备收到的数据才传送到这个socket*/
  419.                         if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)+1) ==
  420.                         -1)
  421.                                 perror("WARNING: interface is ignored");
  422.                 }
  423.                 memset(&saddr, 0, sizeof(saddr));
  424.                 saddr.sin_family = AF_INET;
  425.                 if (src.s_addr)
  426.                 {
  427.                         saddr.sin_addr = src;
  428.                         if (bind(probe_fd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1)
  429.                         {
  430.                                 perror("bind");
  431.                                 exit(2);
  432.                         }
  433.                 }
  434.                 else if (!dad)
  435.                 {
  436.                         int on = 1;
  437.                         int alen = sizeof(saddr);

  438.                         saddr.sin_port = htons(1025);
  439.                         saddr.sin_addr = dst;
  440.                 /*SO_DONTROUTE的作用:don't send via a gateway,only send to directly connected hosts*/
  441.                         if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, (char*)&on, sizeof(on)) == -1)
  442.                                 perror("WARNING: setsockopt(SO_DONTROUTE)");
  443.                         if (connect(probe_fd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1)
  444.                         {
  445.                                 perror("connect");
  446.                                 exit(2);
  447.                         }
  448.                         /*getsockname returns the local IP address and local port number assigned to the
  449.                         connection by
  450.                         the kernel*/
  451.                         if (getsockname(probe_fd, (struct sockaddr*)&saddr, &alen) == -1)
  452.                         {
  453.                                 perror("getsockname");
  454.                                 exit(2);
  455.                         }
  456.                         /*这是最终目的,取得本机IP地址*/
  457.                         src = saddr.sin_addr;
  458.                 }
  459.                 close(probe_fd);
  460.         }

  461.         me.sll_family = AF_PACKET;
  462.         me.sll_ifindex = ifindex;
  463.         me.sll_protocol = htons(ETH_P_ARP);
  464.         /* 只想要由me指定的接口收到的数据包*/
  465.         if (bind(s, (struct sockaddr*)&me, sizeof(me)) == -1) {
  466.                 perror("bind");
  467.                 exit(2);
  468.         }

  469.         if (1) {
  470.                 int alen = sizeof(me);
  471.                 /*get link layer information   是下面这些.因为sll_family sll_ifindex sll_protocol已知
  472.                   unsigned short  sll_hatype;            Header type
  473.                   unsigned char   sll_pkttype;           Packet type
  474.                   unsigned char   sll_halen;             Length of address
  475.                   unsigned char   sll_addr[8];           Physical layer address */
  476.                 if (getsockname(s, (struct sockaddr*)&me, &alen) == -1) {
  477.                         perror("getsockname");
  478.                         exit(2);
  479.                 }
  480.         }
  481.         if (me.sll_halen == 0) {
  482.                 if (!quiet)
  483.                         printf("Interface \"%s\" is not ARPable (no ll address)\n", device);
  484.                 exit(dad?0:2);
  485.         }

  486.         he = me;
  487.         /*把他的地址设为ff:ff:ff:ff:ff:ff  即广播地址,当然假设是以太网*/
  488.         memset(he.sll_addr, -1, he.sll_halen);

  489.         if (!quiet) {
  490.                 printf("ARPING %s ", inet_ntoa(dst));
  491.                 printf("from %s %s\n",  inet_ntoa(src), device ? : "");
  492.         }

  493.         if (!src.s_addr && !dad) {
  494.                 fprintf(stderr, "arping: no source address in not-DAD mode\n");
  495.                 exit(2);
  496.         }

  497.         set_signal(SIGINT, finish);
  498.         set_signal(SIGALRM, catcher);

  499.         catcher();

  500.         while(1) {
  501.                 sigset_t sset, osset;
  502.                 char packet[4096];
  503.                 struct sockaddr_ll from;
  504.                 int alen = sizeof(from);
  505.                 int cc;
  506.                 /*注意s的类型是SOCK_DGRAM,所以收到的数据包里没有link layer info,这些信息被记录在from里*/
  507.                 if ((cc = recvfrom(s, packet, sizeof(packet), 0,
  508.                                    (struct sockaddr *)&from, &alen)) < 0) {
  509.                         perror("arping: recvfrom");
  510.                         continue;
  511.                 }
  512.                 sigemptyset(&sset);
  513.                 sigaddset(&sset, SIGALRM);
  514.                 sigaddset(&sset, SIGINT);
  515.                 sigprocmask(SIG_BLOCK, &sset, &osset);
  516.                 recv_pack(packet, cc, &from);
  517.                 sigprocmask(SIG_SETMASK, &osset, NULL);
  518.         }
  519. }


复制代码

论坛徽章:
0
2 [报告]
发表于 2005-04-02 10:26 |只看该作者

arping代码分析

画的数据包的格式怎么就是不能显示好呢?
请参考TCP/IP Illustrated volume 1

论坛徽章:
0
3 [报告]
发表于 2013-03-12 10:58 |只看该作者
我顶,这个可以用吗????
不懂耶,那个tcp ip书说的没有历程啊
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP