static int icmp_proc(struct netbuf *buf) { int ret = 0; switch (buf->cmd) { case ICMP_CMD_RECV: ret = icmp_recv(buf); break; case ICMP_CMD_SEND: ret = icmp_send(buf); break; default: break; } return ret; }
/*------------------------------------------------------------------------ * xsh_ping - shell command to ping a remote host *------------------------------------------------------------------------ */ shellcmd xsh_ping(int nargs, char *args[]) { uint32 ipaddr; /* IP address in binary */ int32 retval; /* return value */ int32 icmpid; /* ICMP ID to use */ static int32 seq = 0; /* sequence number */ char buf[56]; /* buffer of chars */ int32 i; /* index into buffer */ int32 nextval; /* next value to use */ /* For argument '--help', emit help about the 'ping' command */ if (nargs == 2 && strncmp(args[1], "--help", 7) == 0) { printf("Use: %s address\n\n", args[0]); printf("Description:\n"); printf("\tUse ICMP Echo to ping a remote host\n"); printf("Options:\n"); printf("\t--help\t display this help and exit\n"); printf("\taddress\t an IP address in dotted decimal\n"); return 0; } /* Check for valid number of arguments */ if (nargs != 2) { fprintf(stderr, "%s: invalid arguments\n", args[0]); fprintf(stderr, "Try '%s --help' for more information\n", args[0]); return 1; } /* convert argument to binary */ retval = dot2ip(args[1], &ipaddr); if ((int32)retval == SYSERR) { fprintf(stderr, "%s: invalid IP address\n", args[0]); return 1; } /* Register to receive an ICMP Echo Reply */ icmpid = icmp_register(ipaddr); if (icmpid == SYSERR) { fprintf(stderr, "%s: ICMP registration fails\n", args[0]); return 1; } /* Fill the buffer with values - start with low-order byte of */ /* the sequence number and increment */ nextval = seq; for (i = 0; i<sizeof(buf); i++) { buf[i] = 0xff & nextval++; } /* Send an ICMP Echo Request */ retval = icmp_send(ipaddr, ICMP_ECHOREQST, icmpid, seq++, buf, sizeof(buf)); if (retval == SYSERR) { fprintf(stderr, "%s: cannot send a ping\n", args[0]); icmp_release(icmpid); return 1; } /* Read a reply */ retval = icmp_recv(icmpid, buf, sizeof(buf), 3000); icmp_release(icmpid); if (retval == TIMEOUT) { fprintf(stderr, "%s: no response from %s\n\n", args[0], args[1]); return 1; } fprintf(stderr, "host %s is alive\n", args[1]); return 0; }
static void *recv_loop(void *data) { session_t *session = net_init(ifname, src_ip_addr, 0, 0, 0, ICMP, -1); icmp_packet_t packet; ndp_neighbor_discover_t n_discvr; while(is_initialized) { size_t recv = icmp_recv(session, &packet); if(!recv) continue; switch(packet.type) { case ICMP_TYPE_NEIGHBOR_SOLICITATION: memcpy(n_discvr.buffer, packet.body, recv); if(memcmp(n_discvr.target_addr, session->src_ip, IP_ADDR_LEN) != 0) continue; ndp_option_t opt; memcpy(opt.buffer, n_discvr.options, recv + NDP_ND_HEADER_LEN); if(opt.type != NDP_SOURCE_LINK_ADDR_OPT || opt.len != 1) { fprintf(stderr, "Error: Invalid NDP option type: %d. " "Expected: %d (NDP_SOURCE_LINK_ADDR_OPT)" "\n.", opt.type, NDP_SOURCE_LINK_ADDR_OPT); continue; } ndp_table_insert(session->last_sender_ip, opt.body); ndp_neighbor_discover_t ndp_resp; ndp_option_t opt_resp; memcpy(ndp_resp.target_addr, n_discvr.target_addr, IP_ADDR_LEN); // sol & override flag ndp_resp.reserved = netb_l( 1 << 30 | 1 << 29 ); opt_resp.type = NDP_TARGET_LINK_ADDR_OPT; opt_resp.len = 1; memcpy(opt_resp.body, session->src_addr, ETH_ADDR_LEN); size_t opts_len = NDP_OPT_HEADER_LEN + ETH_ADDR_LEN; memcpy(ndp_resp.options, opt_resp.buffer, opts_len); size_t resp = icmp_send(session, session->last_sender_ip, ICMP_TYPE_NEIGHBOR_ADVERTISEMENT, 0, ndp_resp.buffer, NDP_ND_HEADER_LEN + opts_len); if(resp <= 0) { fprintf(stderr, "Error: Cannot respond with " "ICMP_TYPE_NEIGHBOR_ADVERTISEMENT!\n."); continue; } break; case ICMP_TYPE_NEIGHBOR_ADVERTISEMENT: memcpy(n_discvr.buffer, packet.body, recv); uint8_t zeros[IP_ADDR_LEN] = { 0x0 }; if(memcmp(zeros, n_discvr.target_addr, IP_ADDR_LEN) == 0) continue; // not sure why it's even possible... if(recv <= offsetof(ndp_neighbor_discover_t, options)) continue; // If there's no option, ignore memcpy(opt.buffer, n_discvr.options, recv + NDP_ND_HEADER_LEN); if(opt.type != NDP_TARGET_LINK_ADDR_OPT || opt.len != 1) { fprintf(stderr, "Error: Invalid NDP option type: %d. " "Expected: %d (NDP_TARGET_LINK_ADDR_OPT)" "\n.", opt.type, NDP_TARGET_LINK_ADDR_OPT); continue; } ndp_table_insert(n_discvr.target_addr, opt.body); break; default: break; // unsupported ICMP type } } net_free(session); return 0; }