📄 icmp.c
字号:
{ for (link = UdpLruList.next_bck;; link = link->next_bck) { if (link == &UdpLruList) break; sock = (SOCKET)link; if ((sock->flags & SF_CONNECTED) == FALSE) continue; if ((sock->local.sin_port == src_port) && (sock->remote.sin_port == dst_port) && (sock->local.sin_addr.s_addr == src_addr) && (sock->remote.sin_addr.s_addr == dst_addr)) { sock->soft_error = error; break; } } } /*-------------------------------------------------------------------*/ /* Apply either source quench or error to matching TCP socket. */ /*-------------------------------------------------------------------*/ for (link = TcpLruList.next_bck;; link = link->next_bck) { if (link == &TcpLruList) break; sock = (SOCKET)link; if ((sock->flags & SF_CONNECTED) == FALSE) continue; if ((sock->local.sin_port == src_port) && (sock->remote.sin_port == dst_port) && (sock->local.sin_addr.s_addr == src_addr) && (sock->remote.sin_addr.s_addr == dst_addr)) { if (error == SOURCE_QUENCH) sock->snd_cwnd = sock->snd_mss; else sock->soft_error = error; break; } }}/***********************************************************************//* Global Function Definitions *//***********************************************************************//***********************************************************************//* IcmpDestUR: Send ICMP destination unreachable error response *//* *//* Inputs: code = coded reason that destination is not reachable *//* buf = pointer to buffer containing error packet *//* src = IP address of host that sent bad packet *//* dst = bad packet's destination IP address *//* *//***********************************************************************/void IcmpDestUR(int code, NetBuf *buf, ui32 src, ui32 dst){ simple_msg(ICT_DESTUR, code, buf, src, dst, 0);}/***********************************************************************//* IcmpTimeEx: Send ICMP time exceeded error response *//* *//* Inputs: code = 0/1 (during transit/during fragment assembly) *//* buf = pointer to buffer containing error packet *//* dest = destination IP address *//* *//***********************************************************************/void IcmpTimeEx(int code, NetBuf *buf, ui32 src, ui32 dst){ simple_msg(ICT_TIMEX, code, buf, src, dst, 0);}/***********************************************************************//* IcmpRedirect: Send an ICMP redirect message *//* *//* Inputs: code = ICC_NETRD or ICC_HOSTRD *//* gw = gateway from which packet arrived *//* dest = destination IP address *//* *//***********************************************************************/void IcmpRedirect(int code, ui32 gw, ui32 src, ui32 dst){ simple_msg(ICT_REDIRECT, code, RxBuf, src, dst, gw);}/***********************************************************************//* tcpPing: Send an echo request to a host and decode result *//* *//* Inputs: dst_addr = IP address of host *//* length = length of data in echo request *//* verbose = TRUE if message should be sent to stdout *//* *//* Returns: 0 if no error, else -1 *//* *//***********************************************************************/int tcpPing(ui32 dst_addr, uint length, int verbose){ NetBuf *buf; Ip *ip; Echo *echo; Route *route; int i; static int seq_num; PingEntry *entry; /*-------------------------------------------------------------------*/ /* Verify protocol has been initialized. */ /*-------------------------------------------------------------------*/ if (!Net.Initialized) { NetError(NULL, ENETDOWN); return -1; } /*-------------------------------------------------------------------*/ /* Verify there is a route to this host. */ /*-------------------------------------------------------------------*/ route = RtSearch(dst_addr); if (route == NULL) { NetError(NULL, EHOSTUNREACH); return -1; } /*-------------------------------------------------------------------*/ /* Get network buffer for the echo request. */ /*-------------------------------------------------------------------*/ semPend(Net.IntSem, WAIT_FOREVER); buf = tcpGetBuf(NIMHLEN + IPMHLEN + ICMP_HLEN + length); semPost(Net.IntSem); if (buf == NULL) { NetError(NULL, ENOBUFS); return -1; } /*-------------------------------------------------------------------*/ /* Gain exclusive access to stack internals. */ /*-------------------------------------------------------------------*/ semPend(Net.IntSem, WAIT_FOREVER); /*-------------------------------------------------------------------*/ /* Find free entry in Ping Table. */ /*-------------------------------------------------------------------*/ for (i = 0; PingTbl[i].taskid;) { if (++i == PING_TBL_SZ) { semPend(Net.IntSem, WAIT_FOREVER); tcpRetBuf(&buf); semPost(Net.IntSem); NetError(NULL, ENOBUFS); semPost(Net.IntSem); return -1; } } /*-------------------------------------------------------------------*/ /* Increment ping request sequence number and initialize table. */ /*-------------------------------------------------------------------*/ ++seq_num; entry = &PingTbl[i]; entry->seq_num = htons(seq_num); entry->taskid = RunningTask; entry->soft_error = 0; /*-------------------------------------------------------------------*/ /* Start ICMP header initialization. */ /*-------------------------------------------------------------------*/ echo = buf->ip_data; echo->type = ICT_ECHORQ; echo->code = 0; echo->identifier = 0; echo->seq_num = htons(seq_num); /*-------------------------------------------------------------------*/ /* Initialize echo request data to be a counting pattern. */ /*-------------------------------------------------------------------*/ for (i = 0; i < length; ++i) echo->data[i] = i + 'a'; /*-------------------------------------------------------------------*/ /* Calculate checksum on completed ICMP packet. */ /*-------------------------------------------------------------------*/ echo->checksum = 0; echo->checksum = IpChecksum(echo, ICMP_HLEN + length); /*-------------------------------------------------------------------*/ /* Start IP header initialization and request packet to be sent. */ /*-------------------------------------------------------------------*/ ip = (Ip *)buf->ip_pkt; ip->src_ip = route->ni->ip_addr; ip->dst_ip = dst_addr; icmp_send(buf, ICMP_HLEN + length, ICMP_TOS); /*-------------------------------------------------------------------*/ /* Release internals access and wait up to 3 seconds for reply. */ /*-------------------------------------------------------------------*/ taskLock(); semPost(Net.IntSem); taskSleep(3 * OsTicksPerSec); /*-------------------------------------------------------------------*/ /* Reacquire access long enough to determine timeout or success. */ /*-------------------------------------------------------------------*/ semPend(Net.IntSem, WAIT_FOREVER); if (entry->taskid) { entry->taskid = 0; entry->buf = 0; } buf = entry->buf; semPost(Net.IntSem); /*-------------------------------------------------------------------*/ /* Respond to timeout or ping response. */ /*-------------------------------------------------------------------*/ if (buf == 0) { NetError(NULL, entry->soft_error ? entry->soft_error : ETIMEDOUT); if (verbose) { if (entry->soft_error) perror("Ping error: "); else printf("Request timed out.\n"); } return -1; } else { /*-----------------------------------------------------------------*/ /* Print response statistics if verbose. */ /*-----------------------------------------------------------------*/ if (verbose) { ui16 seq_no; printf("Reply from "); ip = (Ip *)buf->ip_pkt; printIP(ip->src_ip); memcpy(&seq_no, (ui8 *)buf->ip_data + offsetof(Echo, seq_num), 2); printf(": bytes = %u, seq = 0x%04X, TTL = %u\n", ip->length - (IP_HLEN(ip) + ICMP_HLEN), ntohs(seq_no), ip->ttl); } /*-----------------------------------------------------------------*/ /* Free response buffer and return success code. */ /*-----------------------------------------------------------------*/ semPend(Net.IntSem, WAIT_FOREVER); tcpRetBuf(&buf); semPost(Net.IntSem); return 0; }}/***********************************************************************//* IcmpIn: Handle incoming ICMP packet *//* *//***********************************************************************/void IcmpIn(void){ ui8 *ip_data = RxBuf->ip_data; /*-------------------------------------------------------------------*/ /* Verify ICMP checksum. */ /*-------------------------------------------------------------------*/ if (IpChecksum(ip_data, RxBuf->length)) return; /*-------------------------------------------------------------------*/ /* Switch using (possibly unaligned) ICMP message type. */ /*-------------------------------------------------------------------*/ switch (ip_data[0]) { case ICT_ECHORQ: /*-----------------------------------------------------------------*/ /* Respond to an incoming echo request. */ /*-----------------------------------------------------------------*/ { Echo *reply; Ip *ip_out; Ip *ip_in = (Ip *)RxBuf->ip_pkt; NetBuf *rbuf; int id_offset = offsetof(Echo, identifier); /*---------------------------------------------------------------*/ /* Get a network buffer for error message. */ /*---------------------------------------------------------------*/ rbuf = tcpGetBuf(NIMHLEN + IPMHLEN + RxBuf->length); if (rbuf == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -