123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- /*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2010,2011 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <grub/net.h>
- #include <grub/net/ip.h>
- #include <grub/net/netbuff.h>
- struct icmp_header
- {
- grub_uint8_t type;
- grub_uint8_t code;
- grub_uint16_t checksum;
- } GRUB_PACKED;
- struct ping_header
- {
- grub_uint16_t id;
- grub_uint16_t seq;
- } GRUB_PACKED;
- enum
- {
- ICMP_ECHO_REPLY = 0,
- ICMP_ECHO = 8,
- };
- 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;
- grub_err_t err;
- grub_uint16_t checksum;
- /* Ignore broadcast. */
- if (!inf)
- {
- grub_netbuff_free (nb);
- return GRUB_ERR_NONE;
- }
- icmph = (struct icmp_header *) nb->data;
- if (nb->tail - nb->data < (grub_ssize_t) sizeof (*icmph))
- {
- grub_netbuff_free (nb);
- return GRUB_ERR_NONE;
- }
- checksum = icmph->checksum;
- icmph->checksum = 0;
- if (checksum != grub_net_ip_chksum (nb->data, nb->tail - nb->data))
- {
- icmph->checksum = checksum;
- return GRUB_ERR_NONE;
- }
- icmph->checksum = checksum;
- err = grub_netbuff_pull (nb, sizeof (*icmph));
- if (err)
- return err;
- switch (icmph->type)
- {
- case ICMP_ECHO:
- {
- struct grub_net_buff *nb_reply;
- struct icmp_header *icmphr;
- if (icmph->code)
- break;
- nb_reply = grub_netbuff_make_pkt (nb->tail - nb->data + sizeof (*icmphr));
- if (!nb_reply)
- {
- grub_netbuff_free (nb);
- return grub_errno;
- }
- grub_memcpy (nb_reply->data + sizeof (*icmphr), nb->data, nb->tail - nb->data);
- icmphr = (struct icmp_header *) nb_reply->data;
- icmphr->type = ICMP_ECHO_REPLY;
- icmphr->code = 0;
- icmphr->checksum = 0;
- icmphr->checksum = grub_net_ip_chksum ((void *) nb_reply->data,
- nb_reply->tail - nb_reply->data);
- err = grub_net_send_ip_packet (inf, src, ll_src,
- nb_reply, GRUB_NET_IP_ICMP);
- grub_netbuff_free (nb);
- grub_netbuff_free (nb_reply);
- return err;
- }
- };
- grub_netbuff_free (nb);
- return GRUB_ERR_NONE;
- }
|