Beispiel #1
0
grub_net_socket_t
grub_net_udp_open (char *server,
		   grub_uint16_t out_port,
		   grub_err_t (*recv_hook) (grub_net_socket_t sock,
					    struct grub_net_buff *nb,
					    void *data),
		   void *recv_hook_data)
{
  grub_err_t err;
  grub_net_network_level_address_t addr;
  struct grub_net_network_level_interface *inf;
  grub_net_network_level_address_t gateway;
  grub_net_socket_t socket;
  static int in_port = 25300;

  err = grub_net_resolve_address (server, &addr);
  if (err)
    return NULL;
 
  err = grub_net_route_address (addr, &gateway, &inf);
  if (err)
    return NULL;

  socket = grub_zalloc (sizeof (*socket));
  if (socket == NULL)
    return NULL; 

  socket->x_out_port = out_port;
  socket->x_inf = inf;
  socket->x_out_nla = addr;
  socket->x_in_port = in_port++;
  socket->x_status = GRUB_NET_SOCKET_START;
  socket->recv_hook = recv_hook;
  socket->recv_hook_data = recv_hook_data;

  grub_net_socket_register (socket);

  return socket;
}
Beispiel #2
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;
}