changeset 242:56f2780a49bc

RedBoot ICMP patch from Hendrik.Ruijter@axis.com
author msalter
date Tue, 16 Jul 2002 16:25:42 +0000
parents 9cb4b4bc7750
children 52e104cb3184
files packages/redboot/current/ChangeLog packages/redboot/current/include/net/net.h packages/redboot/current/src/net/icmp.c packages/redboot/current/src/net/ping.c packages/redboot/current/src/net/tcp.c
diffstat 5 files changed, 92 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/packages/redboot/current/ChangeLog
+++ b/packages/redboot/current/ChangeLog
@@ -1,3 +1,19 @@
+2002-07-16  Hendrik Ruijter  <Hendrik.Ruijter@axis.com>
+2002-07-16  Mark Salter  <msalter@redhat.com>
+
+	* include/net/net.h: Add __tcp_abort prototype.
+
+	* src/net/icmp.c: The default handler can be replaced by a
+	user defined handler which handles all ICMP segments.
+
+	* src/net/ping.c
+	(handle_icmp): Only ICMP Echo Reply segments must be counted and
+	ICMP Echo Requests are handled in the user defined handler.
+
+	* src/net/tcp.c
+	(do_abort, __tcp_abort): Send an RST flag in order to abort a
+	connection. May use a delay to send the flag.
+
 2002-07-15  Mark Salter  <msalter@redhat.com>
 
 	* src/net/net_io.c: Increase size of out_buf to 1024 bytes.
--- a/packages/redboot/current/include/net/net.h
+++ b/packages/redboot/current/include/net/net.h
@@ -469,6 +469,10 @@ extern void __ip_handler(pktbuf_t *pkt, 
  */
 extern int __ip_send(pktbuf_t *pkt, int protocol, ip_route_t *dest);
 
+/*
+ * Abort connection.
+ */
+extern void __tcp_abort(tcp_socket_t *s, unsigned long delay);
 
 /*
  * Handle incoming ICMP packets.
--- a/packages/redboot/current/src/net/icmp.c
+++ b/packages/redboot/current/src/net/icmp.c
@@ -57,54 +57,70 @@
 /*
  * Handle ICMP packets.
  */
+static void default_icmp_handler(pktbuf_t *pkt, ip_route_t *dest);
 
-static icmp_handler_t icmp_handler;
+static icmp_handler_t icmp_handler = default_icmp_handler;
 
 /*
- * Install a handler for incoming icmp packets.
- * Returns zero if successful, -1 if socket is already used.
+ * Install a user defined user_handler for incoming icmp packets.
+ * Returns zero if successful, -1 if the user_handler is already used.
  */
 int
-__icmp_install_listener(icmp_handler_t handler)
+__icmp_install_listener(icmp_handler_t user_handler)
 {
-    if (icmp_handler) {
+    if (icmp_handler == user_handler) {
         return -1;
     }
-    icmp_handler = handler;
+    icmp_handler = user_handler;
     return 0;
 }
 
 
 /*
- * Remove the handler
+ * Replace a user defined handler by the default handler.
  */
 void
 __icmp_remove_listener(void)
 {
-    icmp_handler = (icmp_handler_t)NULL;
+  if (icmp_handler != default_icmp_handler) {
+      icmp_handler = default_icmp_handler;
+  }
 }
 
+/*
+ * ICMP entry point with an IP packet pkt and the destination dest a reply
+ * should be sent to.
+ */
 void
-__icmp_handler(pktbuf_t *pkt, ip_route_t *r)
+__icmp_handler(pktbuf_t *pkt, ip_route_t *dest)
+{
+    (*icmp_handler)(pkt, dest);
+
+    BSPLOG(bsp_log("icmp: dest[%s] type[%d] seq[%d]\n",
+		   inet_ntoa(pkt->ip_hdr->destination),
+		   pkt->icmp_hdr->type,
+		   pkt->icmp_hdr->seqnum));
+    __pktbuf_free(pkt);
+}
+
+
+/*
+ * The default ICMP handler only handles ICMP incoming echo request and
+ * outgoing echo reply.
+ */
+static void
+default_icmp_handler(pktbuf_t *pkt, ip_route_t *dest)
 {
     word cksum;
 
-    if (pkt->icmp_hdr->type == ICMP_TYPE_ECHOREQUEST &&
-	pkt->icmp_hdr->code == 0 &&
-	__sum((word *)pkt->icmp_hdr, pkt->pkt_bytes, 0) == 0) {
+    if (pkt->icmp_hdr->type == ICMP_TYPE_ECHOREQUEST
+	&& pkt->icmp_hdr->code == 0
+	&& __sum((word *)pkt->icmp_hdr, pkt->pkt_bytes, 0) == 0) {
 
 	pkt->icmp_hdr->type = ICMP_TYPE_ECHOREPLY;
 	pkt->icmp_hdr->checksum = 0;
         cksum = __sum((word *)pkt->icmp_hdr, pkt->pkt_bytes, 0);
 	pkt->icmp_hdr->checksum = htons(cksum);
-	
-	BSPLOG(bsp_log("icmp: seq<%d>\n", pkt->icmp_hdr->seqnum));
-
-	__ip_send(pkt, IP_PROTO_ICMP, r);
-    } else if (icmp_handler) {
-        (*icmp_handler)(pkt, r);
+        __ip_send(pkt, IP_PROTO_ICMP, dest);
     }
-    __pktbuf_free(pkt);
 }
-
-
--- a/packages/redboot/current/src/net/ping.c
+++ b/packages/redboot/current/src/net/ping.c
@@ -74,10 +74,22 @@ static void
 handle_icmp(pktbuf_t *pkt, ip_route_t *src_route)
 {
     icmp_header_t *icmp;
+    unsigned short cksum;
 
     icmp = pkt->icmp_hdr;
-    memcpy(&hold_hdr, icmp, sizeof(*icmp));
-    icmp_received = true;
+    if (icmp->type == ICMP_TYPE_ECHOREQUEST
+	&& icmp->code == 0
+	&& __sum((word *)icmp, pkt->pkt_bytes, 0) == 0) {
+
+	icmp->type = ICMP_TYPE_ECHOREPLY;
+	icmp->checksum = 0;
+        cksum = __sum((word *)icmp, pkt->pkt_bytes, 0);
+	icmp->checksum = htons(cksum);
+        __ip_send(pkt, IP_PROTO_ICMP, src_route);
+    } else if (icmp->type == ICMP_TYPE_ECHOREPLY) {
+        memcpy(&hold_hdr, icmp, sizeof(*icmp));
+        icmp_received = true;
+    }
 }
 
 static void
--- a/packages/redboot/current/src/net/tcp.c
+++ b/packages/redboot/current/src/net/tcp.c
@@ -64,6 +64,8 @@
 #define SEQ_GT(a,b) ((int)((a)-(b)) > 0)
 #define SEQ_GE(a,b) ((int)((a)-(b)) >= 0)
 
+/* Set a timer which will send an RST and abort a connection. */
+static timer_t abort_timer;
 
 static void do_retrans(void *p);
 static void do_close(void *p);
@@ -689,6 +691,25 @@ void
 }
 
 
+/*
+ * Close the tcp connection.
+ */
+static void
+do_abort(void *s)
+{
+    BSPLOG(bsp_log("do_abort: send RST\n"));
+    tcp_send((tcp_socket_t *)s, TCP_FLAG_ACK | TCP_FLAG_RST, 0);
+    __timer_cancel(&abort_timer);
+    ((tcp_socket_t *)s)->state = _CLOSED;
+    free_rxlist((tcp_socket_t *)s);
+    unlink_socket((tcp_socket_t *)s);
+}
+
+void
+__tcp_abort(tcp_socket_t *s, unsigned long delay)
+{
+  __timer_set(&abort_timer, delay, do_abort, s);
+}
 
 /*
  * Close the tcp connection.