From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Jun 2011 19:51:57 +0000 (+0200) Subject: merge mine and abranches' branches. Fix several issues X-Git-Tag: 2.00~1195^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a057797f186e78d895dde4402f3ab76721632fc8;p=thirdparty%2Fgrub.git merge mine and abranches' branches. Fix several issues --- a057797f186e78d895dde4402f3ab76721632fc8 diff --cc grub-core/kern/file.c index 749e72dfc,749e72dfc..2407e72c5 --- a/grub-core/kern/file.c +++ b/grub-core/kern/file.c @@@ -26,6 -26,6 +26,7 @@@ #include grub_err_t (*grub_file_net_seek) (struct grub_file *file, grub_off_t offset) = NULL; ++void (*EXPORT_VAR (grub_grubnet_fini)) (void); grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX]; grub_file_filter_t grub_file_filters_enabled[GRUB_FILE_FILTER_MAX]; diff --cc grub-core/net/arp.c index 1dbd8a58f,6fc7554cd..fecde3282 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@@ -39,16 -39,9 +39,17 @@@ grub_net_arp_resolve (struct grub_net_n struct arphdr *arp_header; grub_net_link_level_address_t target_hw_addr; char *aux, arp_data[128]; + grub_err_t err; int i; + if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && proto_addr->ipv4 == 0xffffffff) + { + hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memset (hw_addr->mac, -1, 6); + return GRUB_ERR_NONE; + } + /* Check cache table. */ entry = arp_find_entry (proto_addr); if (entry) @@@ -60,9 -53,11 +61,12 @@@ nb.head = arp_data; nb.end = arp_data + sizeof (arp_data); grub_netbuff_clear (&nb); - grub_netbuff_reserve (&nb, 128); - grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + 4)); + - if ((err = grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + 4))) != GRUB_ERR_NONE) ++ err = grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + 4)); ++ if (err) + return err; + arp_header = (struct arphdr *) nb.data; arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET); arp_header->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP); diff --cc grub-core/net/ethernet.c index f1bc8c1d0,d33a07010..863e659a8 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@@ -15,8 -15,10 +15,11 @@@ send_ethernet_packet (struct grub_net_n grub_uint16_t ethertype) { struct etherhdr *eth; + grub_err_t err; - grub_netbuff_push (nb, sizeof (*eth)); - if ((err = grub_netbuff_push (nb, sizeof (*eth))) != GRUB_ERR_NONE) ++ err = grub_netbuff_push (nb, sizeof (*eth)); ++ if (err) + return err; eth = (struct etherhdr *) nb->data; grub_memcpy (eth->dst, target_addr.mac, 6); grub_memcpy (eth->src, inf->hwaddress.mac, 6); @@@ -34,11 -35,12 +37,14 @@@ grub_net_recv_ethernet_packet (struct g struct llchdr *llch; struct snaphdr *snaph; grub_uint16_t type; + grub_net_link_level_address_t hwaddress; + grub_err_t err; eth = (struct etherhdr *) nb->data; type = grub_be_to_cpu16 (eth->type); - grub_netbuff_pull (nb, sizeof (*eth)); - if ((err = grub_netbuff_pull (nb, sizeof (*eth))) != GRUB_ERR_NONE) ++ err = grub_netbuff_pull (nb, sizeof (*eth)); ++ if (err) + return err; if (type <= 1500) { @@@ -47,7 -49,8 +53,9 @@@ if (llch->dsap == 0xaa && llch->ssap == 0xaa && llch->ctrl == 0x3) { - grub_netbuff_pull (nb, sizeof (*llch)); - if ((err = grub_netbuff_pull (nb, sizeof (*llch))) != GRUB_ERR_NONE) ++ err = grub_netbuff_pull (nb, sizeof (*llch)); ++ if (err) + return err; snaph = (struct snaphdr *) nb->data; type = snaph->type; } diff --cc grub-core/net/ip.c index 808532a4a,749b41d02..776937a6e --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@@ -65,42 -63,32 +65,44 @@@ grub_net_recv_ip_packets (struct grub_n { struct iphdr *iph = (struct iphdr *) nb->data; grub_err_t err; + struct grub_net_network_level_interface *inf; - if (nb->end - nb->data < (signed) sizeof (*iph)) - return 0; - - if (iph->protocol != 0x11 || - iph->dest != inf->address.ipv4) - return 0; - - grub_netbuff_pull (nb, sizeof (iph)); - err = grub_net_put_packet (&inf->nl_pending, nb); + err = grub_netbuff_pull (nb, sizeof (*iph)); if (err) + return err; + + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { + if (inf->card == card + && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && inf->address.ipv4 == iph->dest + && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) + break; + } + if (!inf) { - grub_print_error (); - return 0; + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + if (inf->card == card + && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC + && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) + break; + } + if (!inf) + { + if (iph->protocol == IP_UDP + && grub_net_hwaddr_cmp (&card->default_address, hwaddress) == 0) + { + struct udphdr *udph; + udph = (struct udphdr *) nb->data; - grub_netbuff_pull (nb, sizeof (*udph)); ++ err = grub_netbuff_pull (nb, sizeof (*udph)); ++ if (err) ++ return err; + if (grub_be_to_cpu16 (udph->dst) == 68) + grub_net_process_dhcp (nb, card); + } + grub_netbuff_free (nb); + return GRUB_ERR_NONE; } - return 1; -} -*/ -grub_err_t -grub_net_recv_ip_packets (struct grub_net_buff *nb) -{ - struct iphdr *iph = (struct iphdr *) nb->data; - grub_err_t err; - - if ((err = grub_netbuff_pull (nb, sizeof (*iph))) != GRUB_ERR_NONE) - return err; switch (iph->protocol) { diff --cc grub-core/net/net.c index 2da60256c,c7732ecbf..5c7d00991 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@@ -1100,130 -1021,14 +1110,139 @@@ grub_cmd_dhcpopt (struct grub_command * "unrecognised format specification %s", args[3]); } +static grub_err_t +grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_card *card; + struct grub_net_network_level_interface *ifaces; + grub_size_t ncards = 0; + unsigned j = 0; + int interval; + grub_err_t err; + + FOR_NET_CARDS (card) + { + if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) + continue; + ncards++; + } + + ifaces = grub_zalloc (ncards * sizeof (ifaces[0])); + if (!ifaces) + return grub_errno; + + j = 0; + FOR_NET_CARDS (card) + { + if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) + continue; + ifaces[j].card = card; + ifaces[j].next = &ifaces[j+1]; + if (j) + ifaces[j].prev = &ifaces[j-1].next; + ifaces[j].name = grub_xasprintf ("%s:dhcp_tmp", card->name); + if (!ifaces[j].name) + { + unsigned i; + for (i = 0; i < j; i++) + grub_free (ifaces[i].name); + grub_free (ifaces); + return grub_errno; + } + ifaces[j].address.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC; + grub_memcpy (&ifaces[j].hwaddress, &card->default_address, + sizeof (ifaces[j].hwaddress)); + j++; + } + ifaces[ncards - 1].next = grub_net_network_level_interfaces; + if (grub_net_network_level_interfaces) + grub_net_network_level_interfaces->prev = & ifaces[ncards - 1].next; + grub_net_network_level_interfaces = &ifaces[0]; + ifaces[0].prev = &grub_net_network_level_interfaces; + for (interval = 200; interval < 10000; interval *= 2) + { + int done = 0; + for (j = 0; j < ncards; j++) + { + struct grub_net_bootp_packet *pack; + struct grub_datetime date; + grub_int32_t t; + struct grub_net_buff *nb; + struct udphdr *udph; + grub_net_network_level_address_t target; + + if (!ifaces[j].prev) + continue; + nb = grub_netbuff_alloc (sizeof (*pack)); + if (!nb) + return grub_errno; + err = grub_netbuff_reserve (nb, sizeof (*pack) + 64 + 128); + if (err) + return err; + err = grub_netbuff_push (nb, sizeof (*pack) + 64); + if (err) + return err; + pack = (void *) nb->data; + done = 1; + grub_memset (pack, 0, sizeof (*pack) + 64); + pack->opcode = 1; + pack->hw_type = 1; + pack->hw_len = 6; + err = grub_get_datetime (&date); + if (err || !grub_datetime2unixtime (&date, &t)) + { + grub_errno = GRUB_ERR_NONE; + t = 0; + } + pack->ident = grub_cpu_to_be32 (t); + pack->seconds = 0;//grub_cpu_to_be16 (t); + + grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6); + + grub_netbuff_push (nb, sizeof (*udph)); + + udph = (struct udphdr *) nb->data; + udph->src = grub_cpu_to_be16 (68); + udph->dst = grub_cpu_to_be16 (67); + udph->chksum = 0; + udph->len = grub_cpu_to_be16 (nb->tail - nb->data); + + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4 = 0xffffffff; + + err = grub_net_send_ip_packet (&ifaces[j], &target, nb); + if (err) + return err; + } + if (!done) + break; + grub_net_poll_cards (interval); + } + + err = GRUB_ERR_NONE; + for (j = 0; j < ncards; j++) + { + if (!ifaces[j].prev) + continue; + grub_error_push (); + grub_net_network_level_interface_unregister (&ifaces[j]); + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't configure %s", + ifaces[j].card->name); + } + + return err; +} + + static void + grub_grubnet_fini_real (void) + { + struct grub_net_card *card; ++ + FOR_NET_CARDS (card) + if (card->driver) + card->driver->fini (card); + } static struct grub_fs grub_net_fs = { diff --cc grub-core/net/tftp.c index 545862092,138020b08..d0ed7c43a --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@@ -154,8 -156,9 +156,10 @@@ tftp_receive (grub_net_socket_t sock, s } grub_netbuff_clear (&nb_ack); grub_netbuff_reserve (&nb_ack, 128); - grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) - + sizeof (tftph->u.ack.block)); - if ((err = grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) - + sizeof (tftph->u.ack.block))) != GRUB_ERR_NONE) ++ err = grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) ++ + sizeof (tftph->u.ack.block)); ++ if (err) + return err; tftph = (struct tftphdr *) nb_ack.data; tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); diff --cc grub-core/net/udp.c index cc7534ea1,b070cbb64..95134c0cf --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@@ -9,8 -9,10 +9,11 @@@ grub_net_send_udp_packet (const grub_ne struct grub_net_buff *nb) { struct udphdr *udph; + grub_err_t err; - grub_netbuff_push (nb, sizeof (*udph)); - if ((err = grub_netbuff_push (nb, sizeof (*udph))) != GRUB_ERR_NONE) ++ err = grub_netbuff_push (nb, sizeof (*udph)); ++ if (err) + return err; udph = (struct udphdr *) nb->data; udph->src = grub_cpu_to_be16 (socket->in_port); diff --cc include/grub/net.h index 5d99cace3,006ec0686..068ccec41 --- a/include/grub/net.h +++ b/include/grub/net.h @@@ -242,6 -239,7 +242,7 @@@ typedef struct grub_ne extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); extern grub_err_t (*EXPORT_VAR (grub_file_net_seek)) (struct grub_file *file, grub_off_t offset); -void (*EXPORT_VAR (grub_grubnet_fini)) (void); ++extern void (*EXPORT_VAR (grub_grubnet_fini)) (void); struct grub_net_network_level_interface {