Пример #1
0
static grub_err_t
ack (tftp_data_t data, grub_uint64_t block)
{
    struct tftphdr *tftph_ack;
    grub_uint8_t nbdata[512];
    struct grub_net_buff nb_ack;
    grub_err_t err;

    nb_ack.head = nbdata;
    nb_ack.end = nbdata + sizeof (nbdata);
    grub_netbuff_clear (&nb_ack);
    grub_netbuff_reserve (&nb_ack, 512);
    err = grub_netbuff_push (&nb_ack, sizeof (tftph_ack->opcode)
                             + sizeof (tftph_ack->u.ack.block));
    if (err)
        return err;

    tftph_ack = (struct tftphdr *) nb_ack.data;
    tftph_ack->opcode = grub_cpu_to_be16_compile_time (TFTP_ACK);
    tftph_ack->u.ack.block = grub_cpu_to_be16 (block);

    err = grub_net_send_udp_packet (data->sock, &nb_ack);
    if (err)
        return err;
    data->ack_sent = block;
    return GRUB_ERR_NONE;
}
Пример #2
0
grub_err_t
grub_net_send_udp_packet (const grub_net_socket_t socket,
			  struct grub_net_buff *nb)
{
  struct udphdr *udph;
  grub_err_t err;

  err = grub_netbuff_push (nb, sizeof (*udph));
  if (err)
    return err;

  udph = (struct udphdr *) nb->data;
  udph->src = grub_cpu_to_be16 (socket->x_in_port);
  udph->dst = grub_cpu_to_be16 (socket->x_out_port);

  /* No chechksum. */
  udph->chksum = 0;
  udph->len = grub_cpu_to_be16 (nb->tail - nb->data);

  return grub_net_send_ip_packet (socket->x_inf, &(socket->x_out_nla), nb);
}
Пример #3
0
static grub_err_t
tftp_close (struct grub_file *file)
{
    tftp_data_t data = file->data;

    if (data->sock)
    {
        grub_uint8_t nbdata[512];
        grub_err_t err;
        struct grub_net_buff nb_err;
        struct tftphdr *tftph;

        nb_err.head = nbdata;
        nb_err.end = nbdata + sizeof (nbdata);

        grub_netbuff_clear (&nb_err);
        grub_netbuff_reserve (&nb_err, 512);
        err = grub_netbuff_push (&nb_err, sizeof (tftph->opcode)
                                 + sizeof (tftph->u.err.errcode)
                                 + sizeof ("closed"));
        if (!err)
        {
            tftph = (struct tftphdr *) nb_err.data;
            tftph->opcode = grub_cpu_to_be16_compile_time (TFTP_ERROR);
            tftph->u.err.errcode = grub_cpu_to_be16_compile_time (TFTP_EUNDEF);
            grub_memcpy (tftph->u.err.errmsg, "closed", sizeof ("closed"));

            err = grub_net_send_udp_packet (data->sock, &nb_err);
        }
        if (err)
            grub_print_error ();
        grub_net_udp_close (data->sock);
    }
    destroy_pq (data);
    grub_free (data);
    return GRUB_ERR_NONE;
}
Пример #4
0
Файл: arp.c Проект: Arvian/GRUB2
grub_err_t
grub_net_arp_send_request (struct grub_net_network_level_interface *inf,
			   const grub_net_network_level_address_t *proto_addr)
{
  struct grub_net_buff nb;
  struct arphdr *arp_header;
  grub_net_link_level_address_t target_hw_addr;
  grub_uint8_t *aux, arp_data[128];
  grub_err_t err;
  int i;
  grub_size_t addrlen;
  grub_uint16_t etherpro;
  grub_uint8_t *nbd;

  if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4)
    {
      addrlen = 4;
      etherpro = GRUB_NET_ETHERTYPE_IP;
    }
  else
    return grub_error (GRUB_ERR_BUG, "unsupported address family");

  /* Build a request packet.  */
  nb.head = arp_data;
  nb.end = arp_data + sizeof (arp_data);
  grub_netbuff_clear (&nb);
  grub_netbuff_reserve (&nb, 128);

  err = grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + addrlen));
  if (err)
    return err;

  arp_header = (struct arphdr *) nb.data;
  arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET);
  arp_header->hln = 6;
  arp_header->pro = grub_cpu_to_be16 (etherpro);
  arp_header->pln = addrlen;
  arp_header->op = grub_cpu_to_be16 (ARP_REQUEST);
  aux = (grub_uint8_t *) arp_header + sizeof (*arp_header);
  /* Sender hardware address.  */
  grub_memcpy (aux, &inf->hwaddress.mac, 6);

  aux += 6;
  /* Sender protocol address */
  grub_memcpy (aux, &inf->address.ipv4, 4);
  aux += addrlen;
  /* Target hardware address */
  for (i = 0; i < 6; i++)
    aux[i] = 0x00;
  aux += 6;
  /* Target protocol address */
  grub_memcpy (aux, &proto_addr->ipv4, 4);
  grub_memset (&target_hw_addr.mac, 0xff, 6);

  nbd = nb.data;
  send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP);
  for (i = 0; i < GRUB_NET_TRIES; i++)
    {
      if (grub_net_link_layer_resolve_check (inf, proto_addr))
	return GRUB_ERR_NONE;
      pending_req = proto_addr->ipv4;
      have_pending = 0;
      grub_net_poll_cards (GRUB_NET_INTERVAL, &have_pending);
      if (grub_net_link_layer_resolve_check (inf, proto_addr))
	return GRUB_ERR_NONE;
      nb.data = nbd;
      send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP);
    }

  return GRUB_ERR_NONE;
}
Пример #5
0
static grub_err_t
tftp_open (struct grub_file *file, const char *filename)
{
    struct tftphdr *tftph;
    char *rrq;
    int i;
    int rrqlen;
    int hdrlen;
    grub_uint8_t open_data[1500];
    struct grub_net_buff nb;
    tftp_data_t data;
    grub_err_t err;
    grub_uint8_t *nbd;
    grub_net_network_level_address_t addr;

    data = grub_zalloc (sizeof (*data));
    if (!data)
        return grub_errno;

    nb.head = open_data;
    nb.end = open_data + sizeof (open_data);
    grub_netbuff_clear (&nb);

    grub_netbuff_reserve (&nb, 1500);
    err = grub_netbuff_push (&nb, sizeof (*tftph));
    if (err)
        return err;

    tftph = (struct tftphdr *) nb.data;

    rrq = (char *) tftph->u.rrq;
    rrqlen = 0;

    tftph->opcode = grub_cpu_to_be16_compile_time (TFTP_RRQ);
    grub_strcpy (rrq, filename);
    rrqlen += grub_strlen (filename) + 1;
    rrq += grub_strlen (filename) + 1;

    grub_strcpy (rrq, "octet");
    rrqlen += grub_strlen ("octet") + 1;
    rrq += grub_strlen ("octet") + 1;

    grub_strcpy (rrq, "blksize");
    rrqlen += grub_strlen ("blksize") + 1;
    rrq += grub_strlen ("blksize") + 1;

    grub_strcpy (rrq, "1024");
    rrqlen += grub_strlen ("1024") + 1;
    rrq += grub_strlen ("1024") + 1;

    grub_strcpy (rrq, "tsize");
    rrqlen += grub_strlen ("tsize") + 1;
    rrq += grub_strlen ("tsize") + 1;

    grub_strcpy (rrq, "0");
    rrqlen += grub_strlen ("0") + 1;
    rrq += grub_strlen ("0") + 1;
    hdrlen = sizeof (tftph->opcode) + rrqlen;

    err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen));
    if (err)
        return err;

    file->not_easily_seekable = 1;
    file->data = data;

    data->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), cmp);
    if (!data->pq)
        return grub_errno;

    err = grub_net_resolve_address (file->device->net->server, &addr);
    if (err)
    {
        destroy_pq (data);
        return err;
    }

    data->sock = grub_net_udp_open (addr,
                                    TFTP_SERVER_PORT, tftp_receive,
                                    file);
    if (!data->sock)
    {
        destroy_pq (data);
        return grub_errno;
    }

    /* Receive OACK packet.  */
    nbd = nb.data;
    for (i = 0; i < GRUB_NET_TRIES; i++)
    {
        nb.data = nbd;
        err = grub_net_send_udp_packet (data->sock, &nb);
        if (err)
        {
            grub_net_udp_close (data->sock);
            destroy_pq (data);
            return err;
        }
        grub_net_poll_cards (GRUB_NET_INTERVAL + (i * GRUB_NET_INTERVAL_ADDITION),
                             &data->have_oack);
        if (data->have_oack)
            break;
    }

    if (!data->have_oack)
        grub_error (GRUB_ERR_TIMEOUT, N_("time out opening `%s'"), filename);
    else
        grub_error_load (&data->save_err);
    if (grub_errno)
    {
        grub_net_udp_close (data->sock);
        destroy_pq (data);
        return grub_errno;
    }

    file->size = data->file_size;

    return GRUB_ERR_NONE;
}