static void icmpSendEcho(struct in_addr to, int opcode, const char *payload, int len) { static pingerEchoData pecho; if (payload && len == 0) len = strlen(payload); assert(len <= PINGER_PAYLOAD_SZ); pecho.to = to; pecho.opcode = (unsigned char) opcode; pecho.psize = len; xmemcpy(pecho.payload, payload, len); icmpSend(&pecho, sizeof(pingerEchoData) - PINGER_PAYLOAD_SZ + len); }
/** * Send an ICMP Echo (Ping) Request. * @param dst destination address * @param id ping stream identifier * @param seq sequence number * @return OK if packet was sent, otherwise SYSERR */ syscall icmpEchoRequest(struct netaddr *dst, ushort id, ushort seq) { struct packet *pkt = NULL; struct icmpEcho *echo = NULL; int result = OK; irqmask im; ICMP_TRACE("echo request(%d, %d)", id, seq); pkt = netGetbuf(); if (SYSERR == (int)pkt) { ICMP_TRACE("Failed to acquire packet buffer"); return SYSERR; } pkt->len = sizeof(struct icmpEcho); pkt->curr -= pkt->len; echo = (struct icmpEcho *)pkt->curr; echo->id = hs2net(id); echo->seq = hs2net(seq); /* Our optional data payload includes room for the departure */ /* and arrival timestamps, in seconds, milliseconds, and */ /* clock cycles. */ im = disable(); echo->timecyc = hl2net(clkcount()); echo->timetic = hl2net(clkticks); echo->timesec = hl2net(clktime); restore(im); echo->arrivcyc = 0; echo->arrivtic = 0; echo->arrivsec = 0; ICMP_TRACE("Sending Echo Request id = %d, seq = %d, time = %d.%d", net2hs(echo->id), net2hs(echo->seq), net2hl(echo->timesec), net2hl(echo->timetic)); result = icmpSend(pkt, ICMP_ECHO, 0, sizeof(struct icmpEcho), dst); netFreebuf(pkt); return result; }
/** * @ingroup icmp * * Compose ICMP Time Exceeded message. * @param unreached packet that could not be sent * @param code ICMP destination unreachable code number * @return OK if packet was sent, otherwise SYSERR */ syscall icmpTimeExceeded(struct packet *unreached, int code) { struct packet *pkt = NULL; struct ipv4Pkt *ip = NULL; struct netaddr dst; int result = OK; int ihl = 0; ICMP_TRACE("Time exceeded (%d)", code); pkt = netGetbuf(); if (SYSERR == (int)pkt) { ICMP_TRACE("Failed to acquire packet buffer"); return SYSERR; } ip = (struct ipv4Pkt *)unreached->nethdr; dst.type = NETADDR_IPv4; dst.len = IPv4_ADDR_LEN; /* Send error message back to original source. */ memcpy(dst.addr, ip->src, dst.len); ihl = (ip->ver_ihl & IPv4_IHL) * 4; /* Message will contain at least ICMP_DEF_DATALEN */ /* of packet in question, as per RFC 792. */ pkt->len = ihl + ICMP_DEF_DATALEN; pkt->curr -= pkt->len; memcpy(pkt->curr, ip, ihl + ICMP_DEF_DATALEN); /* First four octets of payload are unused. */ pkt->curr -= 4; pkt->len += 4; *((ulong *)pkt->curr) = 0; result = icmpSend(pkt, ICMP_TIMEEXCD, code, pkt->len, &dst); netFreebuf(pkt); return result; }