diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index c41e9968a..0c060fe19 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -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) diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index 6b5db9aaa..b38e2c83e 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -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; diff --git a/grub-core/net/icmp.c b/grub-core/net/icmp.c index 9e6bc5c6f..e55a0d86a 100644 --- a/grub-core/net/icmp.c +++ b/grub-core/net/icmp.c @@ -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: diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c index b231f17e9..9a5f3cafe 100644 --- a/grub-core/net/icmp6.c +++ b/grub-core/net/icmp6.c @@ -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; diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 19e12ddac..b56c9d14a 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -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; diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c index 579f94e99..77cf073ee 100644 --- a/grub-core/net/tcp.c +++ b/grub-core/net/tcp.c @@ -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) { diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 2284d8f6c..739541097 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -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 diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index 1b3c0893a..7a8e61479 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -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);