]> git.proxmox.com Git - grub2.git/commitdiff
support routed pings
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 13 Oct 2011 18:53:22 +0000 (20:53 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 13 Oct 2011 18:53:22 +0000 (20:53 +0200)
grub-core/net/bootp.c
grub-core/net/ethernet.c
grub-core/net/icmp.c
grub-core/net/icmp6.c
grub-core/net/ip.c
grub-core/net/tcp.c
grub-core/net/udp.c
include/grub/net/ip.h

index c41e9968ab8abb374bc6e4789bd531503c29808c..0c060fe198b397e0912f600d40d431d4f8819f7f 100644 (file)
@@ -458,6 +458,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)),
          struct grub_net_buff *nb;
          struct udphdr *udph;
          grub_net_network_level_address_t target;
+         grub_net_link_level_address_t ll_target;
 
          if (!ifaces[j].prev)
            continue;
@@ -505,11 +506,15 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)),
          udph->len = grub_cpu_to_be16 (nb->tail - nb->data);
          target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
          target.ipv4 = 0xffffffff;
+         err = grub_net_link_layer_resolve (&ifaces[j], &target, &ll_target);
+         if (err)
+           return err;
+
          udph->chksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP,
                                                         &ifaces[j].address,
                                                         &target);
 
-         err = grub_net_send_ip_packet (&ifaces[j], &target, NULL, nb,
+         err = grub_net_send_ip_packet (&ifaces[j], &target, &ll_target, nb,
                                         GRUB_NET_IP_UDP);
          grub_netbuff_free (nb);
          if (err)
index 6b5db9aaa9c174d81b2a3fb38f2da2e79ed4baa2..b38e2c83ee63c6620c77edd46a6b778d6ceec03a 100644 (file)
@@ -88,6 +88,7 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
   struct snaphdr *snaph;
   grub_net_ethertype_t type;
   grub_net_link_level_address_t hwaddress;
+  grub_net_link_level_address_t src_hwaddress;
   grub_err_t err;
 
   eth = (struct etherhdr *) nb->data;
@@ -113,6 +114,8 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
 
   hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
   grub_memcpy (hwaddress.mac, eth->dst, sizeof (hwaddress.mac));
+  src_hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+  grub_memcpy (src_hwaddress.mac, eth->src, sizeof (src_hwaddress.mac));
 
   switch (type)
     {
@@ -124,7 +127,7 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
       /* IP packet.  */
     case GRUB_NET_ETHERTYPE_IP:
     case GRUB_NET_ETHERTYPE_IP6:
-      return grub_net_recv_ip_packets (nb, card, &hwaddress);
+      return grub_net_recv_ip_packets (nb, card, &hwaddress, &src_hwaddress);
     }
   grub_netbuff_free (nb);
   return GRUB_ERR_NONE;
index 9e6bc5c6fe1c31fc9b04085f04d91de580a3fe01..e55a0d86a52a3ab4248ad4eab89dbea4b11f0358 100644 (file)
@@ -42,6 +42,7 @@ enum
 grub_err_t
 grub_net_recv_icmp_packet (struct grub_net_buff *nb,
                           struct grub_net_network_level_interface *inf,
+                          const grub_net_link_level_address_t *ll_src,
                           const grub_net_network_level_address_t *src)
 {
   struct icmp_header *icmph;
@@ -106,8 +107,7 @@ grub_net_recv_icmp_packet (struct grub_net_buff *nb,
        icmphr->checksum = 0;
        icmphr->checksum = grub_net_ip_chksum ((void *) nb_reply->data,
                                               nb_reply->tail - nb_reply->data);
-       /* FIXME: gateway pings.  */
-       err = grub_net_send_ip_packet (inf, src, NULL,
+       err = grub_net_send_ip_packet (inf, src, ll_src,
                                       nb_reply, GRUB_NET_IP_ICMP);
 
       ping_fail:
index b231f17e90cd0917251b721504bac95f9feea996..9a5f3cafe3a8e0509f0d3541f429da0caa87140b 100644 (file)
@@ -103,6 +103,7 @@ grub_err_t
 grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
                            struct grub_net_card *card,
                            struct grub_net_network_level_interface *inf,
+                           const grub_net_link_level_address_t *ll_src,
                            const grub_net_network_level_address_t *source,
                            const grub_net_network_level_address_t *dest,
                            grub_uint8_t ttl)
@@ -182,8 +183,7 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
                                                           GRUB_NET_IP_ICMPV6,
                                                           &inf->address,
                                                           source);
-       /* FIXME: gateway pings.  */
-       err = grub_net_send_ip_packet (inf, source, NULL, nb_reply,
+       err = grub_net_send_ip_packet (inf, source, ll_src, nb_reply,
                                       GRUB_NET_IP_ICMPV6);
 
       ping_fail:
@@ -289,7 +289,7 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
                                                           GRUB_NET_IP_ICMPV6,
                                                           &inf->address,
                                                           source);
-       err = grub_net_send_ip_packet (inf, source, NULL, nb_reply,
+       err = grub_net_send_ip_packet (inf, source, ll_src, nb_reply,
                                       GRUB_NET_IP_ICMPV6);
 
       ndp_fail:
@@ -444,6 +444,7 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf,
   struct neighbour_solicit *sol;
   struct icmp_header *icmphr;
   grub_net_network_level_address_t multicast;
+  grub_net_link_level_address_t ll_multicast;
   grub_uint8_t *nbd;
   multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
   multicast.ipv6[0] = grub_be_to_cpu64_compile_time (0xff02ULL << 48);
@@ -451,6 +452,10 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf,
                       | (proto_addr->ipv6[1]
                          & grub_be_to_cpu64_compile_time (0xffffff)));
   
+  err = grub_net_link_layer_resolve (inf, &multicast, &ll_multicast);
+  if (err)
+    return err;
+
   nb = grub_netbuff_alloc (sizeof (struct neighbour_solicit)
                           + sizeof (struct option_header)
                           + 6
@@ -499,7 +504,7 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf,
                                                     &inf->address,
                                                     &multicast);
   nbd = nb->data;
-  err = grub_net_send_ip_packet (inf, &multicast, NULL, nb,
+  err = grub_net_send_ip_packet (inf, &multicast, &ll_multicast, nb,
                                 GRUB_NET_IP_ICMPV6);
   if (err)
     goto fail;
@@ -512,7 +517,7 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf,
       if (grub_net_link_layer_resolve_check (inf, proto_addr))
        break;
       nb->data = nbd;
-      err = grub_net_send_ip_packet (inf, &multicast, NULL, nb,
+      err = grub_net_send_ip_packet (inf, &multicast, &ll_multicast, nb,
                                     GRUB_NET_IP_ICMPV6);
       if (err)
        break;
index 19e12ddac17159f3d429ed9df82500d018bde2e8..b56c9d14acb06fa12385d601a609f4ac9b1325dc 100644 (file)
@@ -183,23 +183,16 @@ send_fragmented (struct grub_net_network_level_interface * inf,
 static grub_err_t
 grub_net_send_ip4_packet (struct grub_net_network_level_interface *inf,
                          const grub_net_network_level_address_t *target,
-                         const grub_net_network_level_address_t *gw,
+                         const grub_net_link_level_address_t *ll_target_addr,
                          struct grub_net_buff *nb,
                          grub_net_ip_protocol_t proto)
 {
   struct iphdr *iph;
-  grub_net_link_level_address_t ll_target_addr;
-  grub_err_t err;
 
   COMPILE_TIME_ASSERT (GRUB_NET_OUR_IPV4_HEADER_SIZE == sizeof (*iph));
 
-  /* Determine link layer target address via ARP.  */
-  err = grub_net_link_layer_resolve (inf, gw ? : target, &ll_target_addr);
-  if (err)
-    return err;
-
   if (nb->tail - nb->data + sizeof (struct iphdr) > inf->card->mtu)
-    return send_fragmented (inf, target, nb, proto, ll_target_addr);
+    return send_fragmented (inf, target, nb, proto, *ll_target_addr);
 
   grub_netbuff_push (nb, sizeof (*iph));
   iph = (struct iphdr *) nb->data;
@@ -217,13 +210,14 @@ grub_net_send_ip4_packet (struct grub_net_network_level_interface *inf,
   iph->chksum = 0;
   iph->chksum = grub_net_ip_chksum ((void *) nb->data, sizeof (*iph));
 
-  return send_ethernet_packet (inf, nb, ll_target_addr,
+  return send_ethernet_packet (inf, nb, *ll_target_addr,
                               GRUB_NET_ETHERTYPE_IP);
 }
 
 static grub_err_t
 handle_dgram (struct grub_net_buff *nb,
              struct grub_net_card *card,
+             const grub_net_link_level_address_t *source_hwaddress,
              const grub_net_link_level_address_t *hwaddress,
              grub_net_ip_protocol_t proto,
              const grub_net_network_level_address_t *source,
@@ -325,9 +319,10 @@ handle_dgram (struct grub_net_buff *nb,
     case GRUB_NET_IP_TCP:
       return grub_net_recv_tcp_packet (nb, inf, source);
     case GRUB_NET_IP_ICMP:
-      return grub_net_recv_icmp_packet (nb, inf, source);
+      return grub_net_recv_icmp_packet (nb, inf, source_hwaddress, source);
     case GRUB_NET_IP_ICMPV6:
-      return grub_net_recv_icmp6_packet (nb, card, inf, source, dest, ttl);
+      return grub_net_recv_icmp6_packet (nb, card, inf, source_hwaddress,
+                                        source, dest, ttl);
     default:
       grub_netbuff_free (nb);
       break;
@@ -363,9 +358,10 @@ free_old_fragments (void)
 }
 
 static grub_err_t
-grub_net_recv_ip4_packets (struct grub_net_buff * nb,
-                          struct grub_net_card * card,
-                          const grub_net_link_level_address_t * hwaddress)
+grub_net_recv_ip4_packets (struct grub_net_buff *nb,
+                          struct grub_net_card *card,
+                          const grub_net_link_level_address_t *hwaddress,
+                          const grub_net_link_level_address_t *src_hwaddress)
 {
   struct iphdr *iph = (struct iphdr *) nb->data;
   grub_err_t err;
@@ -439,7 +435,7 @@ grub_net_recv_ip4_packets (struct grub_net_buff * nb,
       dest.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
       dest.ipv4 = iph->dest;
 
-      return handle_dgram (nb, card, hwaddress, iph->protocol,
+      return handle_dgram (nb, card, src_hwaddress, hwaddress, iph->protocol,
                           &source, &dest, iph->ttl);
     }
 
@@ -571,7 +567,8 @@ grub_net_recv_ip4_packets (struct grub_net_buff * nb,
       dest.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
       dest.ipv4 = dst;
 
-      return handle_dgram (ret, card, hwaddress, proto, &source, &dest,
+      return handle_dgram (ret, card, src_hwaddress,
+                          hwaddress, proto, &source, &dest,
                           ttl);
     }
 
@@ -581,21 +578,14 @@ grub_net_recv_ip4_packets (struct grub_net_buff * nb,
 static grub_err_t
 grub_net_send_ip6_packet (struct grub_net_network_level_interface *inf,
                          const grub_net_network_level_address_t *target,
-                         const grub_net_network_level_address_t *gw,
+                         const grub_net_link_level_address_t *ll_target_addr,
                          struct grub_net_buff *nb,
                          grub_net_ip_protocol_t proto)
 {
   struct ip6hdr *iph;
-  grub_net_link_level_address_t ll_target_addr;
-  grub_err_t err;
 
   COMPILE_TIME_ASSERT (GRUB_NET_OUR_IPV6_HEADER_SIZE == sizeof (*iph));
 
-  /* Determine link layer target address via ARP.  */
-  err = grub_net_link_layer_resolve (inf, gw ? : target, &ll_target_addr);
-  if (err)
-    return err;
-
   if (nb->tail - nb->data + sizeof (struct iphdr) > inf->card->mtu)
     return grub_error (GRUB_ERR_NET_PACKET_TOO_BIG, "packet too big");
 
@@ -609,32 +599,33 @@ grub_net_send_ip6_packet (struct grub_net_network_level_interface *inf,
   grub_memcpy (&iph->src, inf->address.ipv6, sizeof (iph->src));
   grub_memcpy (&iph->dest, target->ipv6, sizeof (iph->dest));
 
-  return send_ethernet_packet (inf, nb, ll_target_addr,
+  return send_ethernet_packet (inf, nb, *ll_target_addr,
                               GRUB_NET_ETHERTYPE_IP6);
 }
 
 grub_err_t
 grub_net_send_ip_packet (struct grub_net_network_level_interface *inf,
                         const grub_net_network_level_address_t *target,
-                        const grub_net_network_level_address_t *gw,
+                        const grub_net_link_level_address_t *ll_target_addr,
                         struct grub_net_buff *nb,
                         grub_net_ip_protocol_t proto)
 {
   switch (target->type)
     {
     case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
-      return grub_net_send_ip4_packet (inf, target, gw, nb, proto);
+      return grub_net_send_ip4_packet (inf, target, ll_target_addr, nb, proto);
     case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
-      return grub_net_send_ip6_packet (inf, target, gw, nb, proto);
+      return grub_net_send_ip6_packet (inf, target, ll_target_addr, nb, proto);
     default:
       return grub_error (GRUB_ERR_BAD_ARGUMENT, "not an IP");
     }
 }
 
 static grub_err_t
-grub_net_recv_ip6_packets (struct grub_net_buff * nb,
-                          struct grub_net_card * card,
-                          const grub_net_link_level_address_t * hwaddress)
+grub_net_recv_ip6_packets (struct grub_net_buff *nb,
+                          struct grub_net_card *card,
+                          const grub_net_link_level_address_t *hwaddress,
+                          const grub_net_link_level_address_t *src_hwaddress)
 {
   struct ip6hdr *iph = (struct ip6hdr *) nb->data;
   grub_err_t err;
@@ -684,21 +675,22 @@ grub_net_recv_ip6_packets (struct grub_net_buff * nb,
   grub_memcpy (source.ipv6, &iph->src, sizeof (source.ipv6));
   grub_memcpy (dest.ipv6, &iph->dest, sizeof (dest.ipv6));
 
-  return handle_dgram (nb, card, hwaddress, iph->protocol,
+  return handle_dgram (nb, card, src_hwaddress, hwaddress, iph->protocol,
                       &source, &dest, iph->ttl);
 }
 
 grub_err_t
-grub_net_recv_ip_packets (struct grub_net_buff * nb,
-                         struct grub_net_card * card,
-                         const grub_net_link_level_address_t * hwaddress)
+grub_net_recv_ip_packets (struct grub_net_buff *nb,
+                         struct grub_net_card *card,
+                         const grub_net_link_level_address_t *hwaddress,
+                         const grub_net_link_level_address_t *src_hwaddress)
 {
   struct iphdr *iph = (struct iphdr *) nb->data;
 
   if ((iph->verhdrlen >> 4) == 4)
-    return grub_net_recv_ip4_packets (nb, card, hwaddress);
+    return grub_net_recv_ip4_packets (nb, card, hwaddress, src_hwaddress);
   if ((iph->verhdrlen >> 4) == 6)
-    return grub_net_recv_ip6_packets (nb, card, hwaddress);
+    return grub_net_recv_ip6_packets (nb, card, hwaddress, src_hwaddress);
   grub_dprintf ("net", "Bad IP version: %d\n", (iph->verhdrlen >> 4));
   grub_netbuff_free (nb);
   return GRUB_ERR_NONE;
index 579f94e993e2374a102f4d54588c4bfe251c831c..77cf073ee0f7edc15d388bcbe72703ef6fa1ca1c 100644 (file)
@@ -70,7 +70,8 @@ struct grub_net_tcp_socket
   void (*error_hook) (grub_net_tcp_socket_t sock, void *recv);
   void (*fin_hook) (grub_net_tcp_socket_t sock, void *recv);
   void *hook_data;
-  grub_net_network_level_address_t out_nla, gw;
+  grub_net_network_level_address_t out_nla;
+  grub_net_link_level_address_t ll_target_addr;
   struct grub_net_network_level_interface *inf;
   grub_net_packets_t packs;
   grub_priority_queue_t pq;
@@ -218,7 +219,8 @@ tcp_send (struct grub_net_buff *nb, grub_net_tcp_socket_t socket)
     }
 
   err = grub_net_send_ip_packet (socket->inf, &(socket->out_nla),
-                                &(socket->gw),nb, GRUB_NET_IP_TCP);
+                                &(socket->ll_target_addr), nb,
+                                GRUB_NET_IP_TCP);
   if (err)
     return err;
   nb->data = nbd;
@@ -392,7 +394,7 @@ grub_net_tcp_retransmit (void)
          }
 
        err = grub_net_send_ip_packet (sock->inf, &(sock->out_nla),
-                                      &(sock->gw), unack->nb,
+                                      &(sock->ll_target_addr), unack->nb,
                                       GRUB_NET_IP_TCP);
        unack->nb->data = nbd;
        if (err)
@@ -552,6 +554,7 @@ grub_net_tcp_open (char *server,
   struct tcphdr *tcph;
   int i;
   grub_uint8_t *nbd;
+  grub_net_link_level_address_t ll_target_addr;
 
   err = grub_net_resolve_address (server, &addr);
   if (err)
@@ -568,6 +571,10 @@ grub_net_tcp_open (char *server,
   if (err)
     return NULL;
 
+  err = grub_net_link_layer_resolve (inf, &gateway, &ll_target_addr);
+  if (err)
+    return NULL;
+
   socket = grub_zalloc (sizeof (*socket));
   if (socket == NULL)
     return NULL; 
@@ -575,7 +582,7 @@ grub_net_tcp_open (char *server,
   socket->out_port = out_port;
   socket->inf = inf;
   socket->out_nla = addr;
-  socket->gw = gateway;
+  socket->ll_target_addr = ll_target_addr;
   socket->in_port = in_port++;
   socket->recv_hook = recv_hook;
   socket->error_hook = error_hook;
@@ -629,7 +636,7 @@ grub_net_tcp_open (char *server,
       int j;
       nb->data = nbd;
       err = grub_net_send_ip_packet (socket->inf, &(socket->out_nla), 
-                                    &(socket->gw), nb,
+                                    &(socket->ll_target_addr), nb,
                                     GRUB_NET_IP_TCP);
       if (err)
        {
index 2284d8f6c2947995ad552d0fd6cfb6f877a0196d..7395410970a620b31e49cd9156b74350c48ecaa3 100644 (file)
@@ -34,7 +34,8 @@ struct grub_net_udp_socket
   grub_err_t (*recv_hook) (grub_net_udp_socket_t sock, struct grub_net_buff *nb,
                           void *recv);
   void *recv_hook_data;
-  grub_net_network_level_address_t out_nla, gw;
+  grub_net_network_level_address_t out_nla;
+  grub_net_link_level_address_t ll_target_addr;
   struct grub_net_network_level_interface *inf;
 };
 
@@ -71,6 +72,7 @@ grub_net_udp_open (char *server,
   grub_net_network_level_address_t gateway;
   grub_net_udp_socket_t socket;
   static int in_port = 25300;
+  grub_net_link_level_address_t ll_target_addr;
 
   err = grub_net_resolve_address (server, &addr);
   if (err)
@@ -87,6 +89,10 @@ grub_net_udp_open (char *server,
   if (err)
     return NULL;
 
+  err = grub_net_link_layer_resolve (inf, &gateway, &ll_target_addr);
+  if (err)
+    return NULL;
+
   socket = grub_zalloc (sizeof (*socket));
   if (socket == NULL)
     return NULL; 
@@ -94,7 +100,7 @@ grub_net_udp_open (char *server,
   socket->out_port = out_port;
   socket->inf = inf;
   socket->out_nla = addr;
-  socket->gw = gateway;
+  socket->ll_target_addr = ll_target_addr;
   socket->in_port = in_port++;
   socket->status = GRUB_NET_SOCKET_START;
   socket->recv_hook = recv_hook;
@@ -130,7 +136,8 @@ grub_net_send_udp_packet (const grub_net_udp_socket_t socket,
                                                 &socket->out_nla);
 
   return grub_net_send_ip_packet (socket->inf, &(socket->out_nla),
-                                 &(socket->gw), nb, GRUB_NET_IP_UDP);
+                                 &(socket->ll_target_addr), nb,
+                                 GRUB_NET_IP_UDP);
 }
 
 grub_err_t
index 1b3c0893a98d135a2a0e5f779ee64e53c953b3bd..7a8e614794df555ea77782c9e46bc9ea83eb0010 100644 (file)
@@ -47,23 +47,26 @@ grub_uint16_t grub_net_ip_chksum(void *ipv, grub_size_t len);
 grub_err_t
 grub_net_recv_ip_packets (struct grub_net_buff *nb,
                          struct grub_net_card *card,
-                         const grub_net_link_level_address_t *hwaddress);
+                         const grub_net_link_level_address_t *hwaddress,
+                         const grub_net_link_level_address_t *src_hwaddress);
 
 grub_err_t
 grub_net_send_ip_packet (struct grub_net_network_level_interface *inf,
                         const grub_net_network_level_address_t *target,
-                        const grub_net_network_level_address_t *gw,
+                        const grub_net_link_level_address_t *ll_target_addr,
                         struct grub_net_buff *nb,
                         grub_net_ip_protocol_t proto);
 
 grub_err_t 
 grub_net_recv_icmp_packet (struct grub_net_buff *nb,
                           struct grub_net_network_level_interface *inf,
+                          const grub_net_link_level_address_t *ll_src,
                           const grub_net_network_level_address_t *src);
 grub_err_t
 grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
                            struct grub_net_card *card,
                            struct grub_net_network_level_interface *inf,
+                           const grub_net_link_level_address_t *ll_src,
                            const grub_net_network_level_address_t *source,
                            const grub_net_network_level_address_t *dest,
                            grub_uint8_t ttl);