gonzui


Format: Advanced Search

t2ex/t2ex_source/kernel/sysmain/src/network_sample/ping.cbare sourcepermlink (0.04 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    T2EX Software Package
    4:  *
    5:  *    Copyright 2012 by Ken Sakamura.
    6:  *    This software is distributed under the latest version of T-License 2.x.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by T-Engine Forum(http://www.t-engine.org/) at 2012/12/12.
   10:  *    Modified by TRON Forum(http://www.tron.org/) at 2015/06/04.
   11:  *
   12:  *----------------------------------------------------------------------
   13:  */
   14: /*
   15:  * This software package is available for use, modification, 
   16:  * and redistribution in accordance with the terms of the attached 
   17:  * T-License 2.x.
   18:  * If you want to redistribute the source code, you need to attach 
   19:  * the T-License 2.x document.
   20:  * There's no obligation to publish the content, and no obligation 
   21:  * to disclose it to the TRON Forum if you have modified the 
   22:  * software package.
   23:  * You can also distribute the modified source code. In this case, 
   24:  * please register the modification to T-Kernel traceability service.
   25:  * People can know the history of modifications by the service, 
   26:  * and can be sure that the version you have inherited some 
   27:  * modification of a particular version or not.
   28:  *
   29:  *    http://trace.tron.org/tk/?lang=en
   30:  *    http://trace.tron.org/tk/?lang=ja
   31:  *
   32:  * As per the provisions of the T-License 2.x, TRON Forum ensures that 
   33:  * the portion of the software that is copyrighted by Ken Sakamura or 
   34:  * the TRON Forum does not infringe the copyrights of a third party.
   35:  * However, it does not make any warranty other than this.
   36:  * DISCLAIMER: TRON Forum and Ken Sakamura shall not be held
   37:  * responsible for any consequences or damages caused directly or
   38:  * indirectly by the use of this software package.
   39:  *
   40:  * The source codes in bsd_source.tar.gz in this software package are 
   41:  * derived from NetBSD or OpenBSD and not covered under T-License 2.x.
   42:  * They need to be changed or redistributed according to the 
   43:  * representation of each source header.
   44:  */
   45: 
   46: /*
   47:  *      @(#)ping.c
   48:  *
   49:  */
   50: 
   51: #include <t2ex/socket.h>
   52: #include <tk/tkernel.h>
   53: 
   54: #include <stdio.h>
   55: #include <strings.h>
   56: 
   57: #include "util.h"
   58: 
   59: 
   60: struct icmp_state {
   61:         short xid;
   62:         int seq;
   63:         SYSTIM start_time;
   64: };
   65: 
   66: struct icmp_packet {
   67:         struct ip ip;
   68:         struct icmp icmp;
   69: };
   70: 
   71: static void init_icmp_state(struct icmp_state* state)
   72: {
   73:         bzero(state, sizeof *state);
   74: 
   75:         state->xid = (short)net_random();
   76: }
   77: 
   78: static int recv_icmp_echo_reply(int sd, struct icmp_state* state, int hop)
   79: {
   80:         struct icmp_packet* p;
   81:         char buf[2048];
   82:         int re;
   83:         int i;
   84:         fd_set fds;
   85:         struct timeval tv;
   86:         SYSTIM tim;
   87:         int type;
   88:         char rbuf[18];
   89: 
   90:         bzero(buf, sizeof buf);
   91:         FD_ZERO(&fds);
   92:         FD_SET(sd, &fds);
   93: 
   94:         tv.tv_sec = hop == 0 ? 1 : 3;
   95:         tv.tv_usec = 0;
   96: 
   97:         for(i = 0; i < 3; i++) {
   98:                 re = so_select(sd+1, &fds, NULL, NULL, &tv);
   99:                 DEBUG_PRINT(("recv_icmp_echo_reply: so_select = %d(%d, %d)\n", re, MERCD(re), SERCD(re)));
  100:                 if ( re < 0 ) {
  101:                         return re;
  102:                 } else if ( re == 0 ) {
  103:                         // timed out
  104:                 } else {
  105:                         re = so_recv(sd, buf, sizeof buf, 0);
  106:                         DEBUG_PRINT(("recv_icmp_echo_reply: so_recv = %d(%d, %d)\n", re, MERCD(re), SERCD(re)));
  107: 
  108:                         p = (struct icmp_packet*)buf;
  109: 
  110:                         type = p->icmp.icmp_type;
  111:                         if ( (type != ICMP_ECHOREPLY && type != ICMP_TIMXCEED) || (p->icmp.icmp_type == ICMP_ECHOREPLY && (p->icmp.icmp_id != state->xid || p->icmp.icmp_seq != state->seq ) ) ) {
  112:                                 DEBUG_PRINT(("recv_icmp_echo_reply: type=%d, id=%x:%x, seq=%d:%d\n", type, p->icmp.icmp_id, state->xid, p->icmp.icmp_seq, state->seq));
  113:                                 break;
  114:                         }
  115: 
  116:                         tk_get_tim(&tim);
  117:                         if ( hop == 0 ) {
  118:                                 printf("ICMP reply from %s: %d bytes %d ms TTL=%d\n", inet_ntop(AF_INET, &p->ip.ip_src, rbuf, sizeof(rbuf)), re, tim.lo - state->start_time.lo, p->ip.ip_ttl);
  119:                         } else {
  120:                                 printf(" %2d  %4d ms %s\n", hop, tim.lo - state->start_time.lo, inet_ntop(AF_INET, &p->ip.ip_src, rbuf, sizeof(rbuf)));
  121:                         }
  122:                         if ( type == ICMP_ECHOREPLY || type == ICMP_TIMXCEED ) {
  123:                                 return type;
  124:                         }
  125:                 }
  126:         }
  127: 
  128:         if ( i == 5 ) {
  129:                 return -1;
  130:         }
  131: 
  132:         return 0;
  133: }
  134: 
  135: static int send_icmp_echo_request(int sd, in_addr_t addr, struct icmp_state* state, int ttl)
  136: {
  137:         struct icmp_packet p;
  138:         struct sockaddr_in sa;
  139:         int re;
  140: 
  141:         bzero(&p, sizeof p);
  142: 
  143:         p.ip.ip_v = IPVERSION;
  144:         p.ip.ip_hl = sizeof p.ip >> 2;
  145:         p.ip.ip_len = sizeof p;
  146:         p.ip.ip_id = state->xid;
  147:         p.ip.ip_ttl = ttl != 0 ? ttl : 255;
  148:         p.ip.ip_p = IPPROTO_ICMP;
  149:         p.ip.ip_dst.s_addr = addr;
  150: 
  151:         p.icmp.icmp_type = ICMP_ECHO;
  152:         p.icmp.icmp_id = state->xid;
  153:         p.icmp.icmp_seq = ++state->seq;
  154:         p.icmp.icmp_cksum = checksum((unsigned short*)&p.icmp, sizeof p.icmp);
  155: 
  156:         bzero(&sa, sizeof sa);
  157:         sa.sin_len = sizeof sa;
  158:         sa.sin_family = AF_INET;
  159:         sa.sin_addr.s_addr = addr;
  160: 
  161:         tk_get_tim(&state->start_time);
  162: 
  163:         printf("sending ICMP packet: id=%x, seq=%d\n", state->xid, state->seq);
  164:         re = so_sendto(sd, &p, sizeof p, 0, (struct sockaddr*)&sa, sizeof sa);
  165:         DEBUG_PRINT(("send_icmp_echo_request: so_sendto = %d(%d, %d)\n", re, MERCD(re), SERCD(re)));
  166: 
  167:         return re;
  168: }
  169: 
  170: void ping(in_addr_t addr)
  171: {
  172:         struct icmp_state state;
  173:         int sender, receiver;
  174:         int re;
  175:         int on = 1;
  176: 
  177:         init_icmp_state(&state);
  178: 
  179:         sender = so_socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
  180:         DEBUG_PRINT(("ping: so_socket = %d(%d, %d)\n", sender, MERCD(sender), SERCD(sender)));
  181:         receiver = so_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
  182:         DEBUG_PRINT(("ping: so_socket = %d(%d, %d)\n", receiver, MERCD(receiver), SERCD(receiver)));
  183: 
  184:         re = so_setsockopt(sender, IPPROTO_IP, IP_HDRINCL, &on, sizeof on);
  185:         DEBUG_PRINT(("ping: so_setsockopt = %d(%d, %d)\n", re, MERCD(re), SERCD(re)));
  186: 
  187:         send_icmp_echo_request(sender, addr, &state, 0);
  188:         recv_icmp_echo_reply(receiver, &state, 0);
  189: 
  190:         so_close(sender);
  191:         so_close(receiver);
  192: }
  193: 
  194: void traceroute(in_addr_t addr)
  195: {
  196:         struct icmp_state state;
  197:         int sender, receiver;
  198:         int hop;
  199:         int re;
  200:         int on = 1;
  201:         struct in_addr a;
  202:         char rbuf[18];
  203: 
  204:         init_icmp_state(&state);
  205: 
  206:         sender = so_socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
  207:         DEBUG_PRINT(("traceroute: so_socket = %d(%d, %d)\n", sender, MERCD(sender), SERCD(sender)));
  208:         receiver = so_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
  209:         DEBUG_PRINT(("traceroute: so_socket = %d(%d, %d)\n", receiver, MERCD(receiver), SERCD(receiver)));
  210: 
  211:         re = so_setsockopt(sender, IPPROTO_IP, IP_HDRINCL, &on, sizeof on);
  212:         DEBUG_PRINT(("traceroute: so_setsockopt = %d(%d, %d)\n", re, MERCD(re), SERCD(re)));
  213: 
  214:         a.s_addr = addr;
  215:         printf("traceroute to %s, 30 hops max\n", inet_ntop(AF_INET, &a, rbuf, sizeof(rbuf)));
  216:         for(hop = 1; hop <= 30; hop++) {
  217:                 if ( hop != 1 ) {
  218:                         tk_dly_tsk(1000);
  219:                 }
  220:                 send_icmp_echo_request(sender, addr, &state, hop);
  221:                 re = recv_icmp_echo_reply(receiver, &state, hop);
  222:                 if ( re == ICMP_ECHOREPLY ) {
  223:                         break;
  224:                 }
  225:         }
  226: 
  227:         so_close(sender);
  228:         so_close(receiver);
  229: }