diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index bd5d78160..5cacb6851 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1380,4 +1380,21 @@ module = { module = { name = net; common = net/net.c; -}; \ No newline at end of file + common = net/ip.c; + common = net/udp.c; + common = net/ethernet.c; + common = net/arp.c; + common = net/interface.c; + common = net/netbuff.c; +}; + +module = { + name = tftp; + common = net/tftp.c; +}; + +module = { + name = ofnet; + ieee1275 = net/drivers/ieee1275/ofnet.c; + enable = ieee1275; +}; diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index fcd43f617..6670804b7 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -22,11 +22,17 @@ #include #include #include +#include +#include +#include +#include +#include enum grub_ieee1275_parse_type { GRUB_PARSE_FILENAME, GRUB_PARSE_PARTITION, + GRUB_PARSE_DEVICE }; /* Walk children of 'devpath', calling hook for each. */ @@ -366,12 +372,14 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype) ret = grub_strndup (args, (grub_size_t)(comma - args)); } } - else + + else if (!grub_strcmp ("network", type)) + { + if (ptype == GRUB_PARSE_DEVICE) + ret = grub_strdup(device); + } + else { - /* XXX Handle net devices by configuring & registering a grub_net_dev - here, then return its name? - Example path: "net:,,,,,". */ grub_printf ("Unsupported type %s for device %s\n", type, device); } @@ -381,6 +389,12 @@ fail: return ret; } +char * +grub_ieee1275_get_aliasdevname (const char *path) +{ + return grub_ieee1275_parse_args (path, GRUB_PARSE_DEVICE); +} + char * grub_ieee1275_get_filename (const char *path) { @@ -423,3 +437,4 @@ grub_reboot (void) for (;;) ; } #endif + diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c new file mode 100644 index 000000000..5e10938ae --- /dev/null +++ b/grub-core/net/arp.c @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +static struct arp_entry arp_table[SIZE_ARP_TABLE]; +static grub_int8_t new_table_entry = -1; + +static +void arp_init_table(void) +{ + grub_memset (arp_table, 0, sizeof (arp_table)); + new_table_entry = 0; +} + +static struct arp_entry * +arp_find_entry (const grub_net_network_level_address_t *proto) +{ + grub_uint8_t i; + for(i=0;i < SIZE_ARP_TABLE; i++) + { + if(arp_table[i].avail == 1 && + arp_table[i].nl_address.ipv4 == proto->ipv4) + return &(arp_table[i]); + } + return NULL; +} + +grub_err_t +grub_net_arp_resolve(struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr, + grub_net_link_level_address_t *hw_addr) +{ + struct arp_entry *entry; + struct grub_net_buff *nb; + struct arphdr *arp_header; + grub_net_link_level_address_t target_hw_addr; + grub_uint8_t *aux, i; + + /* Check cache table */ + entry = arp_find_entry (proto_addr); + if (entry) + { + *hw_addr = entry->ll_address; + return GRUB_ERR_NONE; + } + /* Build a request packet */ + nb = grub_malloc (2048); + grub_netbuff_reserve(nb, 2048); + grub_netbuff_push(nb, sizeof(*arp_header) + 2 * (6 + 6)); + arp_header = (struct arphdr *)nb->data; + arp_header->hrd = 0; + arp_header->pro = 0; + arp_header->hln = 6; + arp_header->pln = 6; + arp_header->op = 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 += 6; + /* 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); + + send_ethernet_packet (inf, nb, target_hw_addr, ARP_ETHERTYPE); + grub_netbuff_clear(nb); + grub_netbuff_reserve(nb, 2048); + + grub_uint64_t start_time, current_time; + start_time = grub_get_time_ms(); + do + { + grub_net_recv_ethernet_packet (inf, nb, ARP_ETHERTYPE); + /* Now check cache table again */ + entry = arp_find_entry(proto_addr); + if (entry) + { + grub_memcpy(hw_addr, &entry->ll_address, sizeof (*hw_addr)); + grub_netbuff_clear(nb); + return GRUB_ERR_NONE; + } + current_time = grub_get_time_ms(); + if (current_time - start_time > TIMEOUT_TIME_MS) + break; + } while (! entry); + grub_netbuff_clear(nb); + return grub_error (GRUB_ERR_TIMEOUT, "Timeout: could not resolve hardware address."); +} + +grub_err_t +grub_net_arp_receive(struct grub_net_network_level_interface *inf, + struct grub_net_buff *nb) +{ + struct arphdr *arp_header = (struct arphdr *)nb->data; + struct arp_entry *entry; + grub_uint8_t merge = 0; + grub_uint8_t *sender_hardware_address, *sender_protocol_address; + grub_uint8_t *target_hardware_address, *target_protocol_address; + grub_net_network_level_address_t hwaddress; + + sender_hardware_address = (grub_uint8_t *)arp_header + sizeof(*arp_header); + sender_protocol_address = sender_hardware_address + arp_header->hln; + target_hardware_address = sender_protocol_address + arp_header->pln; + target_protocol_address = target_hardware_address + arp_header->hln; + grub_memcpy (&hwaddress.ipv4, sender_protocol_address, 4); + /* Check if the sender is in the cache table */ + entry = arp_find_entry(&hwaddress); + /* Update sender hardware address */ + if (entry) + { + grub_memcpy(entry->ll_address.mac, sender_hardware_address, 6); + merge = 1; + } + /* Am I the protocol address target? */ + if (! grub_memcmp(target_protocol_address, inf->hwaddress.mac, 6)) + { + /* Add sender to cache table */ + if (! merge) + { + if (new_table_entry == -1) + arp_init_table(); + entry = &(arp_table[new_table_entry]); + entry->avail = 1; + grub_memcpy(&entry->nl_address.ipv4, sender_protocol_address, 4); + grub_memcpy(entry->ll_address.mac, sender_hardware_address, 6); + new_table_entry++; + if (new_table_entry == SIZE_ARP_TABLE) + new_table_entry = 0; + } + if (arp_header->op == ARP_REQUEST) + { + grub_net_link_level_address_t aux; + /* Swap hardware fields */ + grub_memcpy(target_hardware_address, sender_hardware_address, arp_header->hln); + grub_memcpy(sender_hardware_address, inf->hwaddress.mac, 6); + grub_memcpy(aux.mac, sender_protocol_address, 6); + grub_memcpy(sender_protocol_address, target_protocol_address, arp_header->pln); + grub_memcpy(target_protocol_address, aux.mac, arp_header->pln); + /* Change operation to REPLY and send packet */ + arp_header->op = ARP_REPLY; + grub_memcpy (aux.mac, target_hardware_address, 6); + send_ethernet_packet (inf, nb, aux, ARP_ETHERTYPE); + } + } + return GRUB_ERR_NONE; +} diff --git a/grub-core/net/device.c b/grub-core/net/device.c new file mode 100644 index 000000000..e69de29bb diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c new file mode 100644 index 000000000..064f3d280 --- /dev/null +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -0,0 +1,175 @@ +#include +#include +#include +#include + +static +grub_err_t card_open (struct grub_net_card *dev) +{ + + struct grub_ofnetcard_data *data = dev->data; + return grub_ieee1275_open (data->path,&(data->handle)); +} + +static +grub_err_t card_close (struct grub_net_card *dev) +{ + + struct grub_ofnetcard_data *data = dev->data; + + if (data->handle) + grub_ieee1275_close (data->handle); + return GRUB_ERR_NONE; +} + +static +grub_err_t send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) +{ + + int actual; + struct grub_ofnetcard_data *data = dev->data; + + return grub_ieee1275_write (data->handle,pack->data,pack->tail - pack->data,&actual); +} + +static +grub_err_t get_card_packet (struct grub_net_card *dev, struct grub_net_buff *pack) +{ + + int actual, rc; + struct grub_ofnetcard_data *data = dev->data; + grub_netbuff_clear(pack); + + do + { + rc = grub_ieee1275_read (data->handle,pack->data,1500,&actual); + + }while (actual <= 0 || rc < 0); + grub_netbuff_put (pack, actual); + + return GRUB_ERR_NONE; +} + +static struct grub_net_card_driver ofdriver = +{ + .name = "ofnet", + .init = card_open, + .fini = card_close, + .send = send_card_buffer, + .recv = get_card_packet +}; + +static const struct +{ + char *name; + int offset; +} + +bootp_response_properties[] = +{ + { .name = "bootp-response", .offset = 0 }, + { .name = "dhcp-response", .offset = 0 }, + { .name = "bootpreply-packet", .offset = 0x2a }, +}; + + +grub_bootp_t +grub_getbootp( void ) +{ + grub_bootp_t packet = grub_malloc(sizeof *packet); + void *bootp_response = NULL; + grub_ssize_t size; + unsigned int i; + + for ( i = 0; i < ARRAY_SIZE (bootp_response_properties); i++) + if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, + bootp_response_properties[i].name, + &size) >= 0) + break; + + if (size < 0) + { + grub_printf("Error to get bootp\n"); + return NULL; + } + + if (grub_ieee1275_get_property (grub_ieee1275_chosen, + bootp_response_properties[i].name, + bootp_response , + size, 0) < 0) + { + grub_printf("Error to get bootp\n"); + return NULL; + } + + packet = (void *) ((int)bootp_response + + bootp_response_properties[i].offset); + return packet; +} + +void grub_ofnet_findcards (void) +{ + struct grub_net_card *card; + int i = 0; + + auto int search_net_devices (struct grub_ieee1275_devalias *alias); + + int search_net_devices (struct grub_ieee1275_devalias *alias) + { + if ( !grub_strcmp (alias->type,"network") ) + { + + card = grub_malloc (sizeof (struct grub_net_card)); + struct grub_ofnetcard_data *ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data)); + ofdata->path = grub_strdup (alias->path); + card->data = ofdata; + card->name = grub_xasprintf("eth%d",i++); // grub_strdup (alias->name); + grub_net_card_register (card); + } + return 0; + } + + /*Look at all nodes for devices of the type network*/ + grub_ieee1275_devices_iterate (search_net_devices); + +} + +void grub_ofnet_probecards (void) +{ + struct grub_net_card *card; + struct grub_net_card_driver *driver; + + /*Assign correspondent driver for each device. */ + FOR_NET_CARDS (card) + { + FOR_NET_CARD_DRIVERS (driver) + { + if (driver->init(card) == GRUB_ERR_NONE) + { + card->driver = driver; + continue; + } + } + } +} + +GRUB_MOD_INIT(ofnet) +{ + grub_net_card_driver_register (&ofdriver); + grub_ofnet_findcards(); + grub_ofnet_probecards(); + + /*init tftp stack - will be handled by module subsystem in the future*/ + tftp_ini (); + /*get bootp packet - won't be needed in the future*/ + bootp_pckt = grub_getbootp (); + grub_disknet_init(); +} + +GRUB_MODE_FINI(ofnet) +{ + grub_net_card_driver_unregister (&ofdriver); +} + + + diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c new file mode 100644 index 000000000..d3a34aec6 --- /dev/null +++ b/grub-core/net/ethernet.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +grub_err_t +send_ethernet_packet (struct grub_net_network_level_interface *inf, + struct grub_net_buff *nb, + grub_net_link_level_address_t target_addr, + grub_uint16_t ethertype) +{ + struct etherhdr *eth; + + grub_netbuff_push (nb,sizeof(*eth)); + eth = (struct etherhdr *) nb->data; + grub_memcpy(eth->dst, target_addr.mac, 6); + grub_memcpy(eth->src, inf->hwaddress.mac, 6); + + eth->type = grub_cpu_to_be16 (ethertype); + + return inf->card->driver->send (inf->card,nb); +} + +grub_err_t +grub_net_recv_ethernet_packet (struct grub_net_network_level_interface *inf, + struct grub_net_buff *nb, + grub_uint16_t ethertype) +{ + struct etherhdr *eth; + struct llchdr *llch; + struct snaphdr *snaph; + grub_uint16_t type; + + inf->card->driver->recv (inf->card, nb); + eth = (struct etherhdr *) nb->data; + type = eth->type; + grub_netbuff_pull(nb,sizeof (*eth)); + + if (eth->type <=1500) + { + llch = (struct llchdr *) nb->data; + type = llch->dsap & LLCADDRMASK; + + if (llch->dsap == 0xaa && llch->ssap == 0xaa && llch->ctrl == 0x3) + { + grub_netbuff_pull (nb,sizeof(*llch)); + snaph = (struct snaphdr *) nb->data; + type = snaph->type; + } + } + + /* ARP packet */ + if (type == ARP_ETHERTYPE) + { + grub_net_arp_receive(inf, nb); + if (ethertype == ARP_ETHERTYPE) + return GRUB_ERR_NONE; + } + /* IP packet */ + else if(type == IP_ETHERTYPE && ethertype == IP_ETHERTYPE) + return GRUB_ERR_NONE; + + return GRUB_ERR_NONE; +} diff --git a/grub-core/net/i386/pc/pxe.c b/grub-core/net/i386/pc/pxe.c index dc447d92c..347d8562b 100644 --- a/grub-core/net/i386/pc/pxe.c +++ b/grub-core/net/i386/pc/pxe.c @@ -132,10 +132,8 @@ grub_pxefs_open (struct grub_file *file, const char *name) || grub_strncmp (file->device->net->name, "pxe:", sizeof ("pxe:") - 1) == 0) { - const char *ptr; - - ptr = name + sizeof ("pxe,") - 1; - err = grub_net_resolve_address (name + sizeof ("pxe,") - 1, &addr); + err = grub_net_resolve_address (file->device->net->name + + sizeof ("pxe,") - 1, &addr); if (err) return err; } @@ -298,16 +296,14 @@ static struct grub_fs grub_pxefs_fs = static grub_size_t grub_pxe_recv (struct grub_net_card *dev __attribute__ ((unused)), - void *buf __attribute__ ((unused)), - grub_size_t buflen __attribute__ ((unused))) + struct grub_net_buff *buf __attribute__ ((unused))) { return 0; } static grub_err_t grub_pxe_send (struct grub_net_card *dev __attribute__ ((unused)), - void *buf __attribute__ ((unused)), - grub_size_t buflen __attribute__ ((unused))) + struct grub_net_buff *buf __attribute__ ((unused))) { return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "not implemented"); } diff --git a/grub-core/net/interface.c b/grub-core/net/interface.c new file mode 100644 index 000000000..f17b3e66b --- /dev/null +++ b/grub-core/net/interface.c @@ -0,0 +1,37 @@ +/*#include + +#define INTERFACE_REGISTER_FUNCTIONS(layerprevious,layernext) \ +struct grub_net_##layername_layer_protocol *grub_net_##layername_layer_protocols;\ +\ +void grub_net_##layerprevious_##layernext_interface_register (struct grub_net_##layername_layer_protocol *prot)\ +{\ + grub_list_push (GRUB_AS_LIST_P (&grub_net_##layername_layer_protocols),\ + GRUB_AS_LIST (prot));\ +}\ +\ +void grub_net_##layerprevious_##layernext_interface_unregister (struct grub_net_##layername_layer_protocol *prot);\ +{\ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_##layername_layer_protocols),\ + GRUB_AS_LIST (prot));\ +}\ + +INTERFACE_REGISTER_FUNCTIONS("application","transport"); +INTERFACE_REGISTER_FUNCTIONS("transport","network"); +INTERFACE_REGISTER_FUNCTIONS("network","link"); +INTERFACE_REGISTER_FUNCTIONS("link");*/ + +#include +#include +struct grub_net_protocol_stack + *grub_net_protocol_stack_get (char *name) +{ + struct grub_net_protocol_stack *p; + + for (p = grub_net_protocol_stacks; p; p = p->next) + { + if (!grub_strcmp(p->name,name)) + return p; + } + + return NULL; +} diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c new file mode 100644 index 000000000..264195ad3 --- /dev/null +++ b/grub-core/net/ip.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +grub_uint16_t +ipchksum(void *ipv, int len) +{ + grub_uint16_t *ip = (grub_uint16_t *)ipv; + grub_uint32_t sum = 0; + + len >>= 1; + while (len--) + { + sum += grub_be_to_cpu16 (*(ip++)); + if (sum > 0xFFFF) + sum -= 0xFFFF; + } + + return grub_cpu_to_be16 ((~sum) & 0x0000FFFF); +} + +grub_err_t +grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *target, + struct grub_net_buff *nb) +{ + struct iphdr *iph; + static int id = 0x2400; + grub_net_link_level_address_t ll_target_addr; + grub_err_t err; + + grub_netbuff_push(nb,sizeof(*iph)); + iph = (struct iphdr *) nb->data; + + iph->verhdrlen = ((4 << 4) | 5); + iph->service = 0; + iph->len = grub_cpu_to_be16 (nb->tail - nb-> data); + iph->ident = grub_cpu_to_be16 (++id); + iph->frags = 0; + iph->ttl = 0xff; + iph->protocol = 0x11; + iph->src = inf->address.ipv4; + iph->dest = target->ipv4; + + iph->chksum = 0 ; + iph->chksum = ipchksum((void *)nb->data, sizeof(*iph)); + + /* Determine link layer target address via ARP */ + err = grub_net_arp_resolve(inf, target, &ll_target_addr); + if (err) + return err; + + return send_ethernet_packet (inf, nb, ll_target_addr, IP_ETHERTYPE); +} + +static int +ip_filter (struct grub_net_buff *nb, + struct grub_net_network_level_interface *inf) +{ + struct iphdr *iph = (struct iphdr *) nb->data; + grub_err_t err; + + 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); + if (err) + { + grub_print_error (); + return 0; + } + return 1; +} + +grub_err_t +grub_net_recv_ip_packets (struct grub_net_network_level_interface *inf) +{ + struct grub_net_buff nb; + grub_net_recv_ethernet_packet (inf, &nb, IP_ETHERTYPE); + ip_filter (&nb, inf); + return GRUB_ERR_NONE; +} diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c new file mode 100644 index 000000000..4f6a1da84 --- /dev/null +++ b/grub-core/net/netbuff.c @@ -0,0 +1,94 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 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 . + */ + +#include +#include +#include +#include + + +grub_err_t grub_netbuff_put (struct grub_net_buff *net_buff ,grub_size_t len) +{ + net_buff->tail += len; + if (net_buff->tail > net_buff->end) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "put out of the packet range."); + return GRUB_ERR_NONE; +} + +grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len) +{ + net_buff->tail -= len; + if (net_buff->tail < net_buff->head) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "unput out of the packet range."); + return GRUB_ERR_NONE; +} + +grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len) +{ + net_buff->data -= len; + if (net_buff->data < net_buff->head) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "push out of the packet range."); + return GRUB_ERR_NONE; +} + +grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff ,grub_size_t len) +{ + net_buff->data += len; + if (net_buff->data > net_buff->end) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "pull out of the packet range."); + return GRUB_ERR_NONE; +} + +grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len) +{ + net_buff->data += len; + net_buff->tail += len; + if ((net_buff->tail > net_buff->end) || (net_buff->data > net_buff->end)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "reserve out of the packet range."); + return GRUB_ERR_NONE; +} + +struct grub_net_buff *grub_netbuff_alloc ( grub_size_t len ) +{ + struct grub_net_buff *nb; + void *data; + + if (len < NETBUFFMINLEN) + len = NETBUFFMINLEN; + + len = ALIGN_UP (len,NETBUFF_ALIGN); + data = grub_memalign (NETBUFF_ALIGN, len + sizeof (*nb)); + nb = (struct grub_net_buff *) ((int)data + len); + nb->head = nb->data = nb->tail = data; + nb->end = (char *) nb; + + return nb; +} + +grub_err_t grub_netbuff_free (struct grub_net_buff *net_buff) +{ + grub_free (net_buff->head); + return 0; + +} + +grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff) +{ + net_buff->data = net_buff->tail = net_buff->head; + return 0; +} diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c new file mode 100644 index 000000000..bb518b78f --- /dev/null +++ b/grub-core/net/tftp.c @@ -0,0 +1,215 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct { + int block_size; + int size; +} tftp_file; +static int block; + + +static char *get_tok_val(char **tok, char **val, char **str_opt,char *end); +static void process_option(char *tok, char *val); + +static char * +get_tok_val(char **tok, char **val,char **str_opt,char *end) +{ + char *p = *str_opt; + *tok = p; + p += grub_strlen(p) + 1; + + if(p > end) + return NULL; + + *val = p; + p += grub_strlen(p) + 1; + *str_opt = p; + return *tok; +} + +static void +process_option(char *tok, char *val) +{ + if (!grub_strcmp(tok,"blksize")) + { + tftp_file.block_size = grub_strtoul (val,NULL,0); + return; + } + + if (!grub_strcmp(tok,"tsize")) + { + tftp_file.size = grub_strtoul (val,NULL,0); + return; + } + +} + +//void tftp_open (char *options); + +/*send read request*/ +static grub_err_t +tftp_open (struct grub_file *file, const char *filename) +{ + struct tftphdr *tftph; + char *rrq; + int rrqlen; + int hdrlen; + struct grub_net_buff nb; + grub_net_network_level_address_t addr; + grub_err_t err; + + err = grub_net_resolve_address (file->device->net->name + + sizeof ("tftp,") - 1, &addr); + if (err) + return err; + + grub_memset (&nb, 0, sizeof (nb)); + grub_netbuff_push (&nb,sizeof (*tftph)); + + tftph = (struct tftphdr *) nb.data; + + rrq = (char *) tftph->u.rrq; + rrqlen = 0; + + tftph->opcode = TFTP_RRQ; + grub_strcpy (rrq, filename); + rrqlen += grub_strlen (filename) + 1; + rrq += grub_strlen (filename) + 1; + /*passar opcoes como parametro ou usar default?*/ + + grub_strcpy (rrq,"octet"); + rrqlen += grub_strlen ("octet") + 1; + rrq += grub_strlen ("octet") + 1; + + //grub_strcpy (rrq,"netascii"); + //rrqlen += grub_strlen ("netascii") + 1; + //rrq += grub_strlen ("netascii") + 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; + + grub_netbuff_unput (&nb,nb.tail - (nb.data+hdrlen)); + + grub_net_send_udp_packet (&addr, + &nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT); + + grub_net_send_udp_packet (&addr, &nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT); + /*Receive OACK*/ + grub_netbuff_clear (&nb); + grub_netbuff_reserve (&nb,2048); + file->size = tftp_file.size; + + return grub_net_recv_udp_packet (&addr, &nb, + TFTP_CLIENT_PORT, TFTP_SERVER_PORT); +} + +static grub_ssize_t +tftp_receive (struct grub_file *file, char *buf, grub_size_t len) +{ + struct tftphdr *tftph; + char *token,*value,*temp; + grub_err_t err; + grub_net_network_level_address_t addr; + struct grub_net_buff nb; + + err = grub_net_resolve_address (file->device->net->name + + sizeof ("tftp,") - 1, &addr); + if (err) + return err; + + grub_net_recv_udp_packet (&addr, &nb, + TFTP_CLIENT_PORT, TFTP_SERVER_PORT); + + tftph = (struct tftphdr *) nb.data; + switch (tftph->opcode) + { + case TFTP_OACK: + /*process oack packet*/ + temp = (char *) tftph->u.oack.data; + while(get_tok_val(&token,&value,&temp,nb.tail)) + { + process_option(token,value); + } + + //buff_clean + grub_netbuff_clear(&nb); + // grub_printf("OACK---------------------------------------------------------\n"); + //grub_printf("block_size=%d\n",tftp_file.block_size); + // grub_printf("file_size=%d\n",tftp_file.size); + // grub_printf("OACK---------------------------------------------------------\n"); + block = 0; + break; + case TFTP_DATA: + grub_netbuff_pull (&nb,sizeof (tftph->opcode) + sizeof (tftph->u.data.block)); + if (tftph->u.data.block == block + 1) + { + block = tftph->u.data.block; + grub_memcpy (buf, nb.data, len); + } + else + grub_netbuff_clear(&nb); + break; + case TFTP_ERROR: + grub_netbuff_clear (&nb); + return grub_error (GRUB_ERR_ACCESS_DENIED, (char *)tftph->u.err.errmsg); + break; + } + + nb.data = nb.tail = nb.end; + + grub_netbuff_push (&nb,sizeof (tftph->opcode) + sizeof (tftph->u.ack.block)); + + tftph = (struct tftphdr *) nb.data; + tftph->opcode = TFTP_ACK; + tftph->u.ack.block = block; + + return grub_net_send_udp_packet (&addr, &nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT); +} + +static grub_err_t +tftp_close (struct grub_file *file __attribute__ ((unused))) +{ + return 0; +} + +static struct grub_fs grub_tftp_protocol = +{ + .name = "tftp", + .open = tftp_open, + .read = tftp_receive, + .close = tftp_close +}; + +GRUB_MOD_INIT (tftp) +{ + grub_net_app_level_register (&grub_tftp_protocol); +} + +GRUB_MOD_FINI (tftp) +{ + grub_net_app_level_unregister (&grub_tftp_protocol); +} diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c new file mode 100644 index 000000000..27e23e826 --- /dev/null +++ b/grub-core/net/udp.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +grub_err_t +grub_net_send_udp_packet (const grub_net_network_level_address_t *target, + struct grub_net_buff *nb, grub_uint16_t srcport, + grub_uint16_t destport) +{ + struct udphdr *udph; + struct grub_net_network_level_interface *inf; + grub_err_t err; + grub_net_network_level_address_t gateway; + + err = grub_net_route_address (*target, &gateway, &inf); + if (err) + return err; + + grub_netbuff_push (nb,sizeof(*udph)); + + udph = (struct udphdr *) nb->data; + udph->src = grub_cpu_to_be16 (srcport); + udph->dst = grub_cpu_to_be16 (destport); + + /* No chechksum. */ + udph->chksum = 0; + udph->len = grub_cpu_to_be16 (nb->tail - nb->data); + + return grub_net_send_ip_packet (inf, target, nb); +} + +grub_err_t +grub_net_recv_udp_packet (const grub_net_network_level_address_t *target, + struct grub_net_buff *buf, + grub_uint16_t srcport, grub_uint16_t destport) +{ + grub_err_t err; + struct grub_net_packet *pkt; + struct grub_net_network_level_interface *inf; + grub_net_network_level_address_t gateway; + + err = grub_net_route_address (*target, &gateway, &inf); + if (err) + return err; + + (void) srcport; + + err = grub_net_recv_ip_packets (inf); + + FOR_NET_NL_PACKETS(inf, pkt) + { + struct udphdr *udph; + struct grub_net_buff *nb = pkt->nb; + udph = (struct udphdr *) nb->data; + if (grub_be_to_cpu16 (udph->dst) == destport) + { + grub_net_remove_packet (pkt); + grub_netbuff_pull (nb, sizeof(*udph)); + grub_memcpy (buf, nb, sizeof (buf)); + + return GRUB_ERR_NONE; + } + } + return GRUB_ERR_NONE; +} diff --git a/include/grub/disk.h b/include/grub/disk.h index e7f807e0e..dc8bc5018 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -42,7 +42,8 @@ enum grub_disk_dev_id GRUB_DISK_DEVICE_PXE_ID, GRUB_DISK_DEVICE_SCSI_ID, GRUB_DISK_DEVICE_FILE_ID, - GRUB_DISK_DEVICE_LUKS_ID + GRUB_DISK_DEVICE_LUKS_ID, + GRUB_DISK_DEVICE_OFNET_ID }; struct grub_disk; @@ -118,6 +119,23 @@ struct grub_disk }; typedef struct grub_disk *grub_disk_t; +/* Net Disk */ +enum grub_netdisk_protocol +{ + GRUB_NETDISK_PROTOCOL_TFTP +}; +typedef enum grub_netdisk_protocol grub_netdisk_protocol_t; + +struct grub_netdisk_data +{ + grub_netdisk_protocol_t protocol; + grub_uint32_t server_ip; + grub_uint32_t port; + char *username; + char *password; +}; +typedef struct grub_netdisk_data *grub_netdisk_data_t; + #ifdef GRUB_UTIL struct grub_disk_memberlist { diff --git a/include/grub/err.h b/include/grub/err.h index 493796d62..8b2ba4dde 100644 --- a/include/grub/err.h +++ b/include/grub/err.h @@ -57,7 +57,8 @@ typedef enum GRUB_ERR_ACCESS_DENIED, GRUB_ERR_NET_BAD_ADDRESS, GRUB_ERR_NET_ROUTE_LOOP, - GRUB_ERR_NET_NO_ROUTE + GRUB_ERR_NET_NO_ROUTE, + GRUB_ERR_WAIT } grub_err_t; diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index b30909c68..8fb558fa7 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -24,7 +24,6 @@ #include #include -/* Maps a device alias to a pathname. */ struct grub_ieee1275_devalias { char *name; @@ -65,6 +64,13 @@ struct grub_ieee1275_common_hdr typedef grub_uint32_t grub_ieee1275_ihandle_t; typedef grub_uint32_t grub_ieee1275_phandle_t; +struct grub_ofnetcard_data +{ + char *path; + grub_ieee1275_ihandle_t handle; +}; + +/* Maps a device alias to a pathname. */ extern grub_ieee1275_phandle_t EXPORT_VAR(grub_ieee1275_chosen); extern grub_ieee1275_ihandle_t EXPORT_VAR(grub_ieee1275_mmu); extern int (* EXPORT_VAR(grub_ieee1275_entry_fn)) (void *); @@ -182,9 +188,10 @@ EXPORT_FUNC(grub_ieee1275_map) (grub_addr_t phys, grub_addr_t virt, char *EXPORT_FUNC(grub_ieee1275_encode_devname) (const char *path); char *EXPORT_FUNC(grub_ieee1275_get_filename) (const char *path); - int EXPORT_FUNC(grub_ieee1275_devices_iterate) (int (*hook) (struct grub_ieee1275_devalias * alias)); - +char *EXPORT_FUNC(grub_ieee1275_get_aliasdevname) (const char *path); +void EXPORT_FUNC(grub_ofnet_findcards) (void); +void EXPORT_FUNC(grub_ofnet_probecards) (void); #endif /* ! GRUB_IEEE1275_HEADER */ diff --git a/include/grub/ieee1275/ofnet.h b/include/grub/ieee1275/ofnet.h new file mode 100644 index 000000000..ba4c62630 --- /dev/null +++ b/include/grub/ieee1275/ofnet.h @@ -0,0 +1,73 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2007 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 . + */ + +#ifndef GRUB_OFNET_HEADER +#define GRUB_OFNET_HEADER 1 + +#include +#include +#include + +void grub_ofnet_init(void); +void grub_ofnet_fini(void); + +struct grub_ofnet +{ + /* The net name. */ + const char *name; + + /* The OF device string. */ + char *dev; + /*server ip*/ + char *sip; + /*client ip*/ + char *cip; + /*gateway*/ + char *gat; + /**/ + int type; +}; + +typedef struct grub_ofnet *grub_ofnet_t; + +struct grub_bootp { + grub_uint8_t op; /* 1 = BOOTREQUEST, 2 = BOOTREPLY */ + grub_uint8_t htype; /* Hardware address type. */ + grub_uint8_t hlen; /* Hardware address length */ + grub_uint8_t hops; /* Used by gateways in cross-gateway booting. */ + grub_uint32_t xid; /* Transaction ID */ + grub_uint16_t secs; /* Seconds elapsed. */ + grub_uint16_t unused; /* Unused. */ + grub_uint32_t ciaddr; /* Client IP address, */ + grub_uint32_t yiaddr; /* Client IP address filled by server. */ + grub_uint32_t siaddr; /* Server IP address. */ + grub_uint32_t giaddr; /* Gateway IP address. */ + unsigned char chaddr [16]; /* Client hardware address */ + char sname [64]; /* Server name */ + char file [128]; /* Boot filename */ +// grub_uint32_t filesize ; /*File size (testing)*/ + unsigned char vend [64]; +}; + +typedef struct grub_bootp* grub_bootp_t; + +char * grub_get_filestr(const char * ); +char * grub_ip2str (grub_uint32_t ip); +void grub_get_netinfo (grub_ofnet_t netinfo,grub_bootp_t packet); +grub_bootp_t grub_getbootp (void); +#endif /* ! GRUB_NET_HEADER */ diff --git a/include/grub/net.h b/include/grub/net.h index a0737d574..ad553a69a 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -23,6 +23,9 @@ #include #include #include +#include +#include +#include typedef struct grub_fs *grub_net_app_level_t; @@ -65,12 +68,15 @@ struct grub_net_card; struct grub_net_card_driver { - grub_err_t (*send) (struct grub_net_card *dev, void *buf, - grub_size_t buflen); - grub_size_t (*recv) (struct grub_net_card *dev, void *buf, - grub_size_t buflen); + struct grub_net_card_driver *next; + char *name; + grub_err_t (*init) (struct grub_net_card *dev); + grub_err_t (*fini) (struct grub_net_card *dev); + grub_err_t (*send) (struct grub_net_card *dev, struct grub_net_buff *buf); + grub_size_t (*recv) (struct grub_net_card *dev, struct grub_net_buff *buf); }; + struct grub_net_card { struct grub_net_card *next; @@ -109,7 +115,59 @@ typedef struct grub_net_network_level_netaddress }; } grub_net_network_level_netaddress_t; -struct grub_net_network_level_interface; +typedef struct grub_net_packet +{ + struct grub_net_packet *next; + struct grub_net_packet *prev; + struct grub_net_packets *up; + struct grub_net_buff *nb; +} grub_net_packet_t; + +typedef struct grub_net_packets +{ + struct grub_net_packet *first; + struct grub_net_packet *last; +} grub_net_packets_t; + +#define FOR_PACKETS(cont,var) for (var = (cont).first; var; var = var->next) + +static inline grub_err_t +grub_net_put_packet (grub_net_packets_t *pkts, struct grub_net_buff *nb) +{ + struct grub_net_packet *n; + + n = grub_malloc (sizeof (*n)); + if (!n) + return grub_errno; + + n->nb = nb; + n->next = NULL; + n->prev = NULL; + n->up = pkts; + if (pkts->first) + { + pkts->last->next = n; + pkts->last = n; + n->prev = pkts->last; + } + else + pkts->first = pkts->last = n; + + return GRUB_ERR_NONE; +} + +static inline void +grub_net_remove_packet (grub_net_packet_t *pkt) +{ + if (pkt->prev) + pkt->prev->next = pkt->next; + else + pkt->up->first = pkt->next; + if (pkt->next) + pkt->next->prev = pkt->prev; + else + pkt->up->last = pkt->prev; +} struct grub_net_network_level_interface { @@ -121,6 +179,7 @@ struct grub_net_network_level_interface grub_net_interface_flags_t flags; struct grub_net_bootp_ack *dhcp_ack; grub_size_t dhcp_acklen; + grub_net_packets_t nl_pending; void *data; }; @@ -280,5 +339,25 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; #define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) +grub_err_t grub_net_send_link_layer (struct grub_net_network_level_interface *inf, + struct grub_net_buff *nb, + grub_net_link_level_address_t *target); + +typedef int +(*grub_net_packet_handler_t) (struct grub_net_buff *nb, + struct grub_net_network_level_interface *inf); + +grub_err_t grub_net_recv_link_layer (struct grub_net_network_level_interface *inf, + grub_net_packet_handler_t handler); + +grub_err_t +grub_net_recv_ip_packets (struct grub_net_network_level_interface *inf); + +grub_err_t +grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *target, + struct grub_net_buff *nb); + +#define FOR_NET_NL_PACKETS(inf, var) FOR_PACKETS(inf->nl_pending, var) #endif /* ! GRUB_NET_HEADER */ diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h new file mode 100644 index 000000000..e547669a2 --- /dev/null +++ b/include/grub/net/arp.h @@ -0,0 +1,40 @@ +#ifndef GRUB_NET_ARP_HEADER +#define GRUB_NET_ARP_HEADER 1 +#include +#include +#include + +/* IANA ARP constant to define hardware type as ethernet */ +#define ARPHRD_ETHERNET 1 +/* IANA Ethertype */ +#define ARP_ETHERTYPE 0x806 + +/* Size for cache table */ +#define SIZE_ARP_TABLE 5 + +/* ARP header operation codes */ +#define ARP_REQUEST 1 +#define ARP_REPLY 2 + +struct arp_entry { + int avail; + grub_net_network_level_address_t nl_address; + grub_net_link_level_address_t ll_address; +}; + +struct arphdr { + grub_uint16_t hrd; + grub_uint16_t pro; + grub_uint8_t hln; + grub_uint8_t pln; + grub_uint16_t op; +} __attribute__ ((packed)); + +extern grub_err_t grub_net_arp_receive(struct grub_net_network_level_interface *inf, + struct grub_net_buff *nb); + +extern grub_err_t grub_net_arp_resolve(struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *addr, + grub_net_link_level_address_t *hw_addr); + +#endif diff --git a/include/grub/net/device.h b/include/grub/net/device.h new file mode 100644 index 000000000..9f1b9bf1d --- /dev/null +++ b/include/grub/net/device.h @@ -0,0 +1,7 @@ +struct grub_net_card +{ + struct grub_net_card *next; + char *name; + struct grub_net_card_driver *driver; + void *data; +}; diff --git a/include/grub/net/disknet.h b/include/grub/net/disknet.h new file mode 100644 index 000000000..59aa2a320 --- /dev/null +++ b/include/grub/net/disknet.h @@ -0,0 +1,5 @@ +#ifndef GRUB_DISKNET_HEADER +#define GRUB_DISKNET_HEADER 1 + void grub_disknet_init(void); + void grub_disknet_fini(void); +#endif /* ! GRUB_NET_HEADER */ diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h new file mode 100644 index 000000000..b4f07992b --- /dev/null +++ b/include/grub/net/ethernet.h @@ -0,0 +1,51 @@ +#ifndef GRUB_NET_ETHERNET_HEADER +#define GRUB_NET_ETHERNET_HEADER 1 +#include +#include + +#define LLCADDRMASK 0x7f + +struct etherhdr +{ + grub_uint8_t dst[6]; + grub_uint8_t src[6]; + grub_uint16_t type; +} __attribute__ ((packed)); + +#define PCP(x) x & 0xe000 +#define CFI(x) x & 0x1000 +#define VID(x) x & 0x0fff +#define PRINT_ETH_ADDR(name,addr) grub_printf("%s %x:%x:%x:%x:%x:%x\n",\ + name,\ + addr[0],\ + addr[1],\ + addr[2],\ + addr[3],\ + addr[4],\ + addr[5]\ + ) + +struct llchdr +{ + grub_uint8_t dsap; + grub_uint8_t ssap; + grub_uint8_t ctrl; +} __attribute__ ((packed)); + +struct snaphdr +{ + grub_uint8_t oui[3]; + grub_uint16_t type; +} __attribute__ ((packed)); + +grub_err_t +send_ethernet_packet (struct grub_net_network_level_interface *inf, + struct grub_net_buff *nb, + grub_net_link_level_address_t target_addr, + grub_uint16_t ethertype); +grub_err_t +grub_net_recv_ethernet_packet (struct grub_net_network_level_interface *inf, + struct grub_net_buff *nb, + grub_uint16_t ethertype); + +#endif diff --git a/include/grub/net/ieee1275/interface.h b/include/grub/net/ieee1275/interface.h new file mode 100644 index 000000000..c369e35a6 --- /dev/null +++ b/include/grub/net/ieee1275/interface.h @@ -0,0 +1,10 @@ +#ifndef GRUB_IEEE1275_INTERFACE_HEADER +#define GRUB_IEEE1275_INTERFACE_HEADER 1 + +#include +#include +#include +#include + +grub_bootp_t bootp_pckt; +#endif diff --git a/include/grub/net/interface.h b/include/grub/net/interface.h new file mode 100644 index 000000000..cf24dd22e --- /dev/null +++ b/include/grub/net/interface.h @@ -0,0 +1,70 @@ +#ifndef GRUB_INTERFACE_HEADER +#define GRUB_INTERFACE_HEADER +//#include +#include +#include +#include + +struct grub_net_protocol_stack +{ + struct grub_net_protocol_stack *next; + char *name; + grub_net_protocol_id_t id; + void *interface; +}; + +struct grub_net_application_transport_interface +{ + struct grub_net_transport_network_interface *inner_layer; + void *data; + struct grub_net_application_layer_protocol *app_prot; + struct grub_net_transport_layer_protocol *trans_prot; +}; + +struct grub_net_transport_network_interface +{ + struct grub_net_network_link_interface *inner_layer; + void *data; + struct grub_net_transport_layer_protocol *trans_prot; + struct grub_net_network_layer_protocol *net_prot; +}; + +struct grub_net_network_link_interface +{ + void *data; + struct grub_net_network_layer_protocol *net_prot; + struct grub_net_link_layer_protocol *link_prot; +}; + + +struct grub_net_protocol_stack *grub_net_protocol_stacks; +static inline void +grub_net_stack_register (struct grub_net_protocol_stack *stack) +{ + + grub_list_push (GRUB_AS_LIST_P (&grub_net_protocol_stacks), + GRUB_AS_LIST (stack)); +} +/* +void grub_net_stack_unregister (struct grub_net_protocol_stack *stack) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_protocol_stacks), + GRUB_AS_LIST (stack)); +}*/ + +struct grub_net_protocol_stack *grub_net_protocol_stack_get (char *name); + +/* +static inline void +grub_net_interface_application_transport_register (struct grub_net_application_transport_interface); +static inline void +grub_net_interface_application_transport_unregister (struct grub_net_application_transport_interface); +static inline void +grub_net_interface_transport_network_register (struct grub_net_transport_network_interface); +static inline void +grub_net_interface_transport_network_unregister (struct grub_net_transport_network_interface); +static inline void +grub_net_interface_network_link_register (struct grub_net_network_link_interface); +static inline void +grub_net_interface_network_link_unregister (struct grub_net_network_link_interface);*/ +#endif diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h new file mode 100644 index 000000000..765d8005e --- /dev/null +++ b/include/grub/net/ip.h @@ -0,0 +1,37 @@ +#ifndef GRUB_NET_IP_HEADER +#define GRUB_NET_IP_HEADER 1 +#include + +#define IP_ETHERTYPE 0x800 /* IANA Ethertype */ + +struct iphdr { + grub_uint8_t verhdrlen; + grub_uint8_t service; + grub_uint16_t len; + grub_uint16_t ident; + grub_uint16_t frags; + grub_uint8_t ttl; + grub_uint8_t protocol; + grub_uint16_t chksum; + grub_uint32_t src; + grub_uint32_t dest; +} __attribute__ ((packed)) ; + +struct ip6hdr +{ + grub_uint8_t version:4, priority:4; + grub_uint8_t flow_lbl[3]; + grub_uint16_t payload_len; + grub_uint8_t nexthdr; + grub_uint8_t hop_limit; + grub_uint8_t saddr[16]; + grub_uint8_t daddr[16]; +} __attribute__ ((packed)); + +#define IP_UDP 17 /* UDP protocol */ +#define IP_BROADCAST 0xFFFFFFFF + +grub_uint16_t ipchksum(void *ipv, int len); +void ipv4_ini(void); +void ipv4_fini(void); +#endif diff --git a/include/grub/net/mem.h b/include/grub/net/mem.h new file mode 100644 index 000000000..bbdac512b --- /dev/null +++ b/include/grub/net/mem.h @@ -0,0 +1,9 @@ +#ifndef GRUB_NETMM_H +#define GRUB_NETMM_H 1 + +#include +#include + +void *EXPORT_FUNC(grub_net_malloc) (grub_size_t size); + +#endif /* ! GRUB_MM_H */ diff --git a/include/grub/net/netbuff.h b/include/grub/net/netbuff.h new file mode 100644 index 000000000..8ce508ead --- /dev/null +++ b/include/grub/net/netbuff.h @@ -0,0 +1,30 @@ +#ifndef GRUB_NETBUFF_HEADER +#define GRUB_NETBUFF_HEADER + +#include + +#define NETBUFF_ALIGN 2048 +#define NETBUFFMINLEN 64 + +struct grub_net_buff +{ + /*Pointer to the start of the buffer*/ + char *head; + /*Pointer to the data */ + char *data; + /*Pointer to the tail */ + char *tail; + /*Pointer to the end of the buffer*/ + char *end; +}; + +grub_err_t grub_netbuff_put (struct grub_net_buff *net_buff ,grub_size_t len); +grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len); +grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len); +grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff ,grub_size_t len); +grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len); +grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff); +struct grub_net_buff * grub_netbuff_alloc ( grub_size_t len ); +grub_err_t grub_netbuff_free (struct grub_net_buff *net_buff); +grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff); +#endif diff --git a/include/grub/net/protocol.h b/include/grub/net/protocol.h new file mode 100644 index 000000000..da54b073f --- /dev/null +++ b/include/grub/net/protocol.h @@ -0,0 +1,9 @@ +#ifndef GRUB_PROTOCOL_HEADER +#define GRUB_PROTOCOL_HEADER +#include +#include +#include +#include +#include + +#endif diff --git a/include/grub/net/tftp.h b/include/grub/net/tftp.h new file mode 100644 index 000000000..1f1c48616 --- /dev/null +++ b/include/grub/net/tftp.h @@ -0,0 +1,70 @@ +#ifndef GRUB_NET_TFTP_HEADER +#define GRUB_NET_TFTP_HEADER 1 + +#include +#include +#include + +/* IP port for the MTFTP server used for Intel's PXE */ +#define MTFTP_SERVER_PORT 75 +#define MTFTP_CLIENT_PORT 76 + +#define TFTP_DEFAULTSIZE_PACKET 512 +#define TFTP_MAX_PACKET 1432 + +/* IP port for the TFTP server */ +#define TFTP_SERVER_PORT 69 +#define TFTP_CLIENT_PORT 26300 + + +/* We define these based on what's in arpa/tftp.h. We just like our + * names better, cause they're clearer */ +#define TFTP_RRQ 1 +#define TFTP_WRQ 2 +#define TFTP_DATA 3 +#define TFTP_ACK 4 +#define TFTP_ERROR 5 +#define TFTP_OACK 6 + +#define TFTP_CODE_EOF 1 +#define TFTP_CODE_MORE 2 +#define TFTP_CODE_ERROR 3 +#define TFTP_CODE_BOOT 4 +#define TFTP_CODE_CFG 5 + +#define TFTP_EUNDEF 0 /* not defined */ +#define TFTP_ENOTFOUND 1 /* file not found */ +#define TFTP_EACCESS 2 /* access violation */ +#define TFTP_ENOSPACE 3 /* disk full or allocation exceeded */ +#define TFTP_EBADOP 4 /* illegal TFTP operation */ +#define TFTP_EBADID 5 /* unknown transfer ID */ +#define TFTP_EEXISTS 6 /* file already exists */ +#define TFTP_ENOUSER 7 /* no such user */ +#define TFTP_DEFAULT_FILENAME "kernel" + + /* * own here because this is cleaner, and maps to the same data layout. + * */ +struct tftphdr { + grub_uint16_t opcode; + union { + grub_int8_t rrq[TFTP_DEFAULTSIZE_PACKET]; + struct { + grub_uint16_t block; + grub_int8_t download[TFTP_MAX_PACKET]; + } data; + struct { + grub_uint16_t block; + } ack; + struct { + grub_uint16_t errcode; + grub_int8_t errmsg[TFTP_DEFAULTSIZE_PACKET]; + } err; + struct { + grub_int8_t data[TFTP_DEFAULTSIZE_PACKET+2]; + } oack; + } u; +} __attribute__ ((packed)) ; + +void tftp_ini(void); +void tftp_fini(void); +#endif diff --git a/include/grub/net/type_net.h b/include/grub/net/type_net.h new file mode 100644 index 000000000..f159b1de0 --- /dev/null +++ b/include/grub/net/type_net.h @@ -0,0 +1,33 @@ +#ifndef GRUB_TYPES_NET_HEADER +#define GRUB_TYPES_NET_HEADER 1 +#include + + +#define UDP_PCKT 0x11 +#define IP_PCKT 0x0800 +#define TIMEOUT_TIME_MS 3*1000 +typedef enum +{ + GRUB_NET_TFTP_ID, + GRUB_NET_UDP_ID, + GRUB_NET_IPV4_ID, + GRUB_NET_IPV6_ID, + GRUB_NET_ETHERNET_ID, + GRUB_NET_ARP_ID, + GRUB_NET_DHCP_ID +}grub_net_protocol_id_t; + + +typedef union grub_net_network_layer_netaddress +{ + grub_uint32_t ipv4; +} grub_net_network_layer_address_t; + +typedef union grub_net_network_layer_address +{ + struct { + grub_uint32_t base; + int masksize; + } ipv4; +} grub_net_network_layer_netaddress_t; +#endif diff --git a/include/grub/net/udp.h b/include/grub/net/udp.h new file mode 100644 index 000000000..f1992467d --- /dev/null +++ b/include/grub/net/udp.h @@ -0,0 +1,31 @@ +#ifndef GRUB_NET_UDP_HEADER +#define GRUB_NET_UDP_HEADER 1 +#include +#include + +struct udphdr +{ + grub_uint16_t src; + grub_uint16_t dst; + grub_uint16_t len; + grub_uint16_t chksum; +} __attribute__ ((packed)); + +grub_err_t +grub_net_send_udp_packet (const grub_net_network_level_address_t *target, + struct grub_net_buff *nb, grub_uint16_t srcport, + grub_uint16_t destport); + + +grub_err_t +grub_net_recv_udp_packets (struct grub_net_network_level_interface *inf); + +grub_err_t +grub_net_recv_udp_packet (const grub_net_network_level_address_t *target, + struct grub_net_buff *buf, + grub_uint16_t srcport, grub_uint16_t destport); + +#define FOR_NET_UDP_PACKETS(inf, var) FOR_PACKETS(inf->udp_pending, var) + + +#endif