2
* GRUB -- GRand Unified Bootloader
3
* Copyright (C) 2010,2011 Free Software Foundation, Inc.
5
* GRUB is free software: you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation, either version 3 of the License, or
8
* (at your option) any later version.
10
* GRUB is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20
#include <grub/net/netbuff.h>
21
#include <grub/time.h>
22
#include <grub/file.h>
23
#include <grub/i18n.h>
25
#include <grub/misc.h>
27
#include <grub/command.h>
29
#include <grub/net/ethernet.h>
30
#include <grub/net/arp.h>
31
#include <grub/net/ip.h>
32
#include <grub/loader.h>
33
#include <grub/bufio.h>
34
#include <grub/kernel.h>
36
GRUB_MOD_LICENSE ("GPLv3+");
38
char *grub_net_default_server;
42
struct grub_net_route *next;
43
struct grub_net_route **prev;
44
grub_net_network_level_netaddress_t target;
46
struct grub_net_network_level_protocol *prot;
50
struct grub_net_network_level_interface *interface;
51
grub_net_network_level_address_t gw;
55
struct grub_net_route *grub_net_routes = NULL;
56
struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL;
57
struct grub_net_card *grub_net_cards = NULL;
58
struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL;
59
static struct grub_fs grub_net_fs;
61
struct grub_net_link_layer_entry {
63
grub_net_network_level_address_t nl_address;
64
grub_net_link_level_address_t ll_address;
67
#define LINK_LAYER_CACHE_SIZE 256
69
static struct grub_net_link_layer_entry *
70
link_layer_find_entry (const grub_net_network_level_address_t *proto,
71
const struct grub_net_card *card)
74
if (!card->link_layer_table)
76
for (i = 0; i < LINK_LAYER_CACHE_SIZE; i++)
78
if (card->link_layer_table[i].avail == 1
79
&& grub_net_addr_cmp (&card->link_layer_table[i].nl_address,
81
return &card->link_layer_table[i];
87
grub_net_link_layer_add_address (struct grub_net_card *card,
88
const grub_net_network_level_address_t *nl,
89
const grub_net_link_level_address_t *ll,
92
struct grub_net_link_layer_entry *entry;
94
/* Check if the sender is in the cache table. */
95
entry = link_layer_find_entry (nl, card);
96
/* Update sender hardware address. */
97
if (entry && override)
98
grub_memcpy (&entry->ll_address, ll, sizeof (entry->ll_address));
102
/* Add sender to cache table. */
103
if (card->link_layer_table == NULL)
104
card->link_layer_table = grub_zalloc (LINK_LAYER_CACHE_SIZE
105
* sizeof (card->link_layer_table[0]));
106
entry = &(card->link_layer_table[card->new_ll_entry]);
108
grub_memcpy (&entry->ll_address, ll, sizeof (entry->ll_address));
109
grub_memcpy (&entry->nl_address, nl, sizeof (entry->nl_address));
110
card->new_ll_entry++;
111
if (card->new_ll_entry == LINK_LAYER_CACHE_SIZE)
112
card->new_ll_entry = 0;
116
grub_net_link_layer_resolve_check (struct grub_net_network_level_interface *inf,
117
const grub_net_network_level_address_t *proto_addr)
119
struct grub_net_link_layer_entry *entry;
121
if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
122
&& proto_addr->ipv4 == 0xffffffff)
124
entry = link_layer_find_entry (proto_addr, inf->card);
131
grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf,
132
const grub_net_network_level_address_t *proto_addr,
133
grub_net_link_level_address_t *hw_addr)
135
struct grub_net_link_layer_entry *entry;
138
if ((proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
139
&& proto_addr->ipv4 == 0xffffffff)
140
|| proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV
141
|| (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
142
&& proto_addr->ipv6[0] == grub_be_to_cpu64_compile_time (0xff02ULL
144
&& proto_addr->ipv6[1] == (grub_be_to_cpu64_compile_time (1))))
146
hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
147
grub_memset (hw_addr->mac, -1, 6);
148
return GRUB_ERR_NONE;
151
if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
152
&& ((grub_be_to_cpu64 (proto_addr->ipv6[0]) >> 56) == 0xff))
154
hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
155
hw_addr->mac[0] = 0x33;
156
hw_addr->mac[1] = 0x33;
157
hw_addr->mac[2] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 24) & 0xff);
158
hw_addr->mac[3] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 16) & 0xff);
159
hw_addr->mac[4] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 8) & 0xff);
160
hw_addr->mac[5] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 0) & 0xff);
161
return GRUB_ERR_NONE;
164
/* Check cache table. */
165
entry = link_layer_find_entry (proto_addr, inf->card);
168
*hw_addr = entry->ll_address;
169
return GRUB_ERR_NONE;
171
switch (proto_addr->type)
173
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
174
err = grub_net_arp_send_request (inf, proto_addr);
176
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
177
err = grub_net_icmp6_send_request (inf, proto_addr);
179
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
180
return grub_error (GRUB_ERR_BUG, "shouldn't reach here");
182
return grub_error (GRUB_ERR_BUG,
183
"unsupported address type %d", proto_addr->type);
187
entry = link_layer_find_entry (proto_addr, inf->card);
190
*hw_addr = entry->ll_address;
191
return GRUB_ERR_NONE;
193
return grub_error (GRUB_ERR_TIMEOUT,
194
N_("timeout: could not resolve hardware address"));
198
grub_net_card_unregister (struct grub_net_card *card)
200
struct grub_net_network_level_interface *inf, *next;
201
FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE(inf, next)
202
if (inf->card == card)
203
grub_net_network_level_interface_unregister (inf);
206
if (card->driver->close)
207
card->driver->close (card);
210
grub_list_remove (GRUB_AS_LIST (card));
213
static struct grub_net_slaac_mac_list *
214
grub_net_ipv6_get_slaac (struct grub_net_card *card,
215
const grub_net_link_level_address_t *hwaddr)
217
struct grub_net_slaac_mac_list *slaac;
220
for (slaac = card->slaac_list; slaac; slaac = slaac->next)
221
if (grub_net_hwaddr_cmp (&slaac->address, hwaddr) == 0)
224
slaac = grub_zalloc (sizeof (*slaac));
228
slaac->name = grub_malloc (grub_strlen (card->name)
229
+ GRUB_NET_MAX_STR_HWADDR_LEN
230
+ sizeof (":slaac"));
231
ptr = grub_stpcpy (slaac->name, card->name);
232
if (grub_net_hwaddr_cmp (&card->default_address, hwaddr) != 0)
234
ptr = grub_stpcpy (ptr, ":");
235
grub_net_hwaddr_to_str (hwaddr, ptr);
236
ptr += grub_strlen (ptr);
238
ptr = grub_stpcpy (ptr, ":slaac");
240
grub_memcpy (&slaac->address, hwaddr, sizeof (slaac->address));
241
slaac->next = card->slaac_list;
242
card->slaac_list = slaac;
246
struct grub_net_network_level_interface *
247
grub_net_ipv6_get_link_local (struct grub_net_card *card,
248
const grub_net_link_level_address_t *hwaddr)
250
struct grub_net_network_level_interface *inf;
251
char name[grub_strlen (card->name)
252
+ GRUB_NET_MAX_STR_HWADDR_LEN
255
grub_net_network_level_address_t addr;
257
addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
258
addr.ipv6[0] = grub_cpu_to_be64 (0xfe80ULL << 48);
259
addr.ipv6[1] = grub_net_ipv6_get_id (hwaddr);
261
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
263
if (inf->card == card
264
&& grub_net_hwaddr_cmp (&inf->hwaddress, hwaddr) == 0
265
&& grub_net_addr_cmp (&inf->address, &addr) == 0)
269
ptr = grub_stpcpy (name, card->name);
270
if (grub_net_hwaddr_cmp (&card->default_address, hwaddr) != 0)
272
ptr = grub_stpcpy (ptr, ":");
273
grub_net_hwaddr_to_str (hwaddr, ptr);
274
ptr += grub_strlen (ptr);
276
ptr = grub_stpcpy (ptr, ":link");
277
return grub_net_add_addr (name, card, &addr, hwaddr, 0);
280
/* FIXME: allow to specify mac address. */
282
grub_cmd_ipv6_autoconf (struct grub_command *cmd __attribute__ ((unused)),
283
int argc, char **args)
285
struct grub_net_card *card;
286
struct grub_net_network_level_interface **ifaces;
287
grub_size_t ncards = 0;
291
struct grub_net_slaac_mac_list **slaacs;
295
if (argc > 0 && grub_strcmp (card->name, args[0]) != 0)
300
ifaces = grub_zalloc (ncards * sizeof (ifaces[0]));
301
slaacs = grub_zalloc (ncards * sizeof (slaacs[0]));
302
if (!ifaces || !slaacs)
311
if (argc > 0 && grub_strcmp (card->name, args[0]) != 0)
313
ifaces[j] = grub_net_ipv6_get_link_local (card, &card->default_address);
320
slaacs[j] = grub_net_ipv6_get_slaac (card, &card->default_address);
330
for (interval = 200; interval < 10000; interval *= 2)
332
/* FIXME: send router solicitation. */
334
for (j = 0; j < ncards; j++)
336
if (slaacs[j]->slaac_counter)
342
grub_net_poll_cards (interval, 0);
346
for (j = 0; j < ncards; j++)
348
if (slaacs[j]->slaac_counter)
350
err = grub_error (GRUB_ERR_FILE_NOT_FOUND,
351
N_("couldn't autoconfigure %s"),
352
ifaces[j]->card->name);
361
grub_net_route_register (struct grub_net_route *route)
363
grub_list_push (GRUB_AS_LIST_P (&grub_net_routes),
364
GRUB_AS_LIST (route));
368
grub_net_route_unregister (struct grub_net_route *route)
370
grub_list_remove (GRUB_AS_LIST (route));
373
#define FOR_NET_ROUTES(var) for (var = grub_net_routes; var; var = var->next)
376
parse_ip (const char *val, grub_uint32_t *ip, const char **rest)
378
grub_uint32_t newip = 0;
380
const char *ptr = val;
382
for (i = 0; i < 4; i++)
385
t = grub_strtoul (ptr, (char **) &ptr, 0);
388
grub_errno = GRUB_ERR_NONE;
391
if (*ptr != '.' && i == 0)
400
if (i != 3 && *ptr != '.')
404
*ip = grub_cpu_to_le32 (newip);
411
parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
413
grub_uint16_t newip[8];
414
const char *ptr = val;
415
int word, quaddot = -1;
417
if (ptr[0] == ':' && ptr[1] != ':')
422
for (word = 0; word < 8; word++)
432
t = grub_strtoul (ptr, (char **) &ptr, 16);
435
grub_errno = GRUB_ERR_NONE;
440
newip[word] = grub_cpu_to_be16 (t);
445
if (quaddot == -1 && word < 7)
449
grub_memmove (&newip[quaddot + 7 - word], &newip[quaddot],
450
(word - quaddot + 1) * sizeof (newip[0]));
451
grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0]));
453
grub_memcpy (ip, newip, 16);
460
match_net (const grub_net_network_level_netaddress_t *net,
461
const grub_net_network_level_address_t *addr)
463
if (net->type != addr->type)
467
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
469
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
471
grub_uint32_t mask = (0xffffffffU << (32 - net->ipv4.masksize));
472
if (net->ipv4.masksize == 0)
474
return ((grub_be_to_cpu32 (net->ipv4.base) & mask)
475
== (grub_be_to_cpu32 (addr->ipv4) & mask));
477
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
479
grub_uint64_t mask[2];
480
if (net->ipv6.masksize <= 64)
482
mask[0] = 0xffffffffffffffffULL << (64 - net->ipv6.masksize);
487
mask[0] = 0xffffffffffffffffULL;
488
mask[1] = 0xffffffffffffffffULL << (128 - net->ipv6.masksize);
490
return (((grub_be_to_cpu64 (net->ipv6.base[0]) & mask[0])
491
== (grub_be_to_cpu64 (addr->ipv6[0]) & mask[0]))
492
&& ((grub_be_to_cpu64 (net->ipv6.base[1]) & mask[1])
493
== (grub_be_to_cpu64 (addr->ipv6[1]) & mask[1])));
500
grub_net_resolve_address (const char *name,
501
grub_net_network_level_address_t *addr)
505
grub_size_t naddresses;
506
struct grub_net_network_level_address *addresses = 0;
508
if (parse_ip (name, &addr->ipv4, &rest) && *rest == 0)
510
addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
511
return GRUB_ERR_NONE;
513
if (parse_ip6 (name, addr->ipv6, &rest) && *rest == 0)
515
addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
516
return GRUB_ERR_NONE;
518
err = grub_net_dns_lookup (name, 0, 0, &naddresses, &addresses, 1);
522
grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("unresolvable address %s"),
524
/* FIXME: use other results as well. */
525
*addr = addresses[0];
526
grub_free (addresses);
527
return GRUB_ERR_NONE;
531
grub_net_resolve_net_address (const char *name,
532
grub_net_network_level_netaddress_t *addr)
535
if (parse_ip (name, &addr->ipv4.base, &rest))
537
addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
540
addr->ipv4.masksize = grub_strtoul (rest + 1, (char **) &rest, 0);
541
if (!grub_errno && *rest == 0)
542
return GRUB_ERR_NONE;
543
grub_errno = GRUB_ERR_NONE;
547
addr->ipv4.masksize = 32;
548
return GRUB_ERR_NONE;
551
if (parse_ip6 (name, addr->ipv6.base, &rest))
553
addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
556
addr->ipv6.masksize = grub_strtoul (rest + 1, (char **) &rest, 0);
557
if (!grub_errno && *rest == 0)
558
return GRUB_ERR_NONE;
559
grub_errno = GRUB_ERR_NONE;
563
addr->ipv6.masksize = 128;
564
return GRUB_ERR_NONE;
567
return grub_error (GRUB_ERR_NET_BAD_ADDRESS,
568
N_("unrecognised network address `%s'"),
573
route_cmp (const struct grub_net_route *a, const struct grub_net_route *b)
575
if (a == NULL && b == NULL)
581
if (a->target.type < b->target.type)
583
if (a->target.type > b->target.type)
585
switch (a->target.type)
587
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
589
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
590
if (a->target.ipv6.masksize > b->target.ipv6.masksize)
592
if (a->target.ipv6.masksize < b->target.ipv6.masksize)
595
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
596
if (a->target.ipv4.masksize > b->target.ipv4.masksize)
598
if (a->target.ipv4.masksize < b->target.ipv4.masksize)
606
grub_net_route_address (grub_net_network_level_address_t addr,
607
grub_net_network_level_address_t *gateway,
608
struct grub_net_network_level_interface **interf)
610
struct grub_net_route *route;
611
unsigned int depth = 0;
612
unsigned int routecnt = 0;
613
struct grub_net_network_level_protocol *prot = NULL;
614
grub_net_network_level_address_t curtarget = addr;
618
FOR_NET_ROUTES(route)
621
for (depth = 0; depth < routecnt + 2 && depth < GRUB_UINT_MAX; depth++)
623
struct grub_net_route *bestroute = NULL;
624
FOR_NET_ROUTES(route)
626
if (depth && prot != route->prot)
628
if (!match_net (&route->target, &curtarget))
630
if (route_cmp (route, bestroute) > 0)
633
if (bestroute == NULL)
634
return grub_error (GRUB_ERR_NET_NO_ROUTE,
635
N_("destination unreachable"));
637
if (!bestroute->is_gateway)
639
*interf = bestroute->interface;
640
return GRUB_ERR_NONE;
643
*gateway = bestroute->gw;
644
curtarget = bestroute->gw;
647
return grub_error (GRUB_ERR_NET_ROUTE_LOOP,
648
/* TRANSLATORS: route loop is a condition when e.g.
649
to contact server A you need to go through B
650
and to contact B you need to go through A. */
651
N_("route loop detected"));
655
grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)),
656
int argc, char **args)
658
struct grub_net_network_level_interface *inter;
661
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
663
FOR_NET_NETWORK_LEVEL_INTERFACES (inter)
664
if (grub_strcmp (inter->name, args[0]) == 0)
667
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("address not found"));
669
if (inter->flags & GRUB_NET_INTERFACE_PERMANENT)
670
return grub_error (GRUB_ERR_IO,
671
N_("you can't delete this address"));
673
grub_net_network_level_interface_unregister (inter);
674
grub_free (inter->name);
677
return GRUB_ERR_NONE;
681
grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf)
683
switch (target->type)
685
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
686
/* TRANSLATORS: it refers to the network address. */
687
grub_strncpy (buf, "temporary", GRUB_NET_MAX_STR_ADDR_LEN);
689
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
692
grub_uint64_t n = grub_be_to_cpu64 (target->ipv6[0]);
694
for (i = 0; i < 4; i++)
696
grub_snprintf (ptr, 6, "%" PRIxGRUB_UINT64_T ":",
697
(n >> (48 - 16 * i)) & 0xffff);
698
ptr += grub_strlen (ptr);
700
n = grub_be_to_cpu64 (target->ipv6[1]);
701
for (i = 0; i < 3; i++)
703
grub_snprintf (ptr, 6, "%" PRIxGRUB_UINT64_T ":",
704
(n >> (48 - 16 * i)) & 0xffff);
705
ptr += grub_strlen (ptr);
707
grub_snprintf (ptr, 5, "%" PRIxGRUB_UINT64_T, n & 0xffff);
710
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
712
grub_uint32_t n = grub_be_to_cpu32 (target->ipv4);
713
grub_snprintf (buf, GRUB_NET_MAX_STR_ADDR_LEN, "%d.%d.%d.%d",
714
((n >> 24) & 0xff), ((n >> 16) & 0xff),
715
((n >> 8) & 0xff), ((n >> 0) & 0xff));
719
grub_snprintf (buf, GRUB_NET_MAX_STR_ADDR_LEN,
720
"Unknown address type %d", target->type);
725
grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str)
730
case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET:
734
for (ptr = str, i = 0; i < ARRAY_SIZE (addr->mac); i++)
736
grub_snprintf (ptr, GRUB_NET_MAX_STR_HWADDR_LEN - (ptr - str),
737
"%02x:", addr->mac[i] & 0xff);
738
ptr += (sizeof ("XX:") - 1);
743
grub_printf (_("Unsupported hw address type %d\n"), addr->type);
747
grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a,
748
const grub_net_link_level_address_t *b)
750
if (a->type < b->type)
752
if (a->type > b->type)
756
case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET:
757
return grub_memcmp (a->mac, b->mac, sizeof (a->mac));
759
grub_printf (_("Unsupported hw address type %d\n"), a->type);
764
grub_net_addr_cmp (const grub_net_network_level_address_t *a,
765
const grub_net_network_level_address_t *b)
767
if (a->type < b->type)
769
if (a->type > b->type)
773
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
774
return grub_memcmp (&a->ipv4, &b->ipv4, sizeof (a->ipv4));
775
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
776
return grub_memcmp (&a->ipv6, &b->ipv6, sizeof (a->ipv6));
777
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
780
grub_printf (_("Unsupported address type %d\n"), a->type);
784
/* FIXME: implement this. */
786
hwaddr_set_env (struct grub_env_var *var __attribute__ ((unused)),
787
const char *val __attribute__ ((unused)))
792
/* FIXME: implement this. */
794
addr_set_env (struct grub_env_var *var __attribute__ ((unused)),
795
const char *val __attribute__ ((unused)))
801
defserver_set_env (struct grub_env_var *var __attribute__ ((unused)),
804
grub_free (grub_net_default_server);
805
grub_net_default_server = grub_strdup (val);
806
return grub_strdup (val);
810
defserver_get_env (struct grub_env_var *var __attribute__ ((unused)),
811
const char *val __attribute__ ((unused)))
813
return grub_net_default_server ? : "";
818
grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter)
821
char buf[GRUB_NET_MAX_STR_HWADDR_LEN];
822
char name[grub_strlen (inter->name) + sizeof ("net__mac")];
824
grub_net_hwaddr_to_str (&inter->hwaddress, buf);
825
grub_snprintf (name, sizeof (name), "net_%s_mac", inter->name);
826
for (ptr = name; *ptr; ptr++)
829
grub_env_set (name, buf);
830
grub_register_variable_hook (name, 0, hwaddr_set_env);
834
char buf[GRUB_NET_MAX_STR_ADDR_LEN];
835
char name[grub_strlen (inter->name) + sizeof ("net__ip")];
837
grub_net_addr_to_str (&inter->address, buf);
838
grub_snprintf (name, sizeof (name), "net_%s_ip", inter->name);
839
for (ptr = name; *ptr; ptr++)
842
grub_env_set (name, buf);
843
grub_register_variable_hook (name, 0, addr_set_env);
846
inter->card->num_ifaces++;
847
inter->prev = &grub_net_network_level_interfaces;
848
inter->next = grub_net_network_level_interfaces;
850
inter->next->prev = &inter->next;
851
grub_net_network_level_interfaces = inter;
854
struct grub_net_network_level_interface *
855
grub_net_add_addr (const char *name,
856
struct grub_net_card *card,
857
const grub_net_network_level_address_t *addr,
858
const grub_net_link_level_address_t *hwaddress,
859
grub_net_interface_flags_t flags)
861
struct grub_net_network_level_interface *inter;
863
inter = grub_zalloc (sizeof (*inter));
867
inter->name = grub_strdup (name);
868
grub_memcpy (&(inter->address), addr, sizeof (inter->address));
869
grub_memcpy (&(inter->hwaddress), hwaddress, sizeof (inter->hwaddress));
870
inter->flags = flags;
872
inter->dhcp_ack = NULL;
873
inter->dhcp_acklen = 0;
875
grub_net_network_level_interface_register (inter);
881
grub_net_add_ipv4_local (struct grub_net_network_level_interface *inter,
884
grub_uint32_t ip_cpu;
885
struct grub_net_route *route;
887
if (inter->address.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4)
890
ip_cpu = grub_be_to_cpu32 (inter->address.ipv4);
894
if (!(ip_cpu & 0x80000000))
896
else if (!(ip_cpu & 0x40000000))
898
else if (!(ip_cpu & 0x20000000))
904
route = grub_zalloc (sizeof (*route));
908
route->name = grub_xasprintf ("%s:local", inter->name);
915
route->target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
916
route->target.ipv4.base = grub_cpu_to_be32 (ip_cpu & (0xffffffff << (32 - mask)));
917
route->target.ipv4.masksize = mask;
918
route->is_gateway = 0;
919
route->interface = inter;
921
grub_net_route_register (route);
926
/* FIXME: support MAC specifying. */
928
grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)),
929
int argc, char **args)
931
struct grub_net_card *card;
932
grub_net_network_level_address_t addr;
934
grub_net_interface_flags_t flags = 0;
935
struct grub_net_network_level_interface *inf;
938
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("three arguments expected"));
941
if (grub_strcmp (card->name, args[1]) == 0)
944
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found"));
946
err = grub_net_resolve_address (args[2], &addr);
950
if (card->flags & GRUB_NET_CARD_NO_MANUAL_INTERFACES)
951
return grub_error (GRUB_ERR_IO,
952
"this card doesn't support address addition");
954
if (card->flags & GRUB_NET_CARD_HWADDRESS_IMMUTABLE)
955
flags |= GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE;
957
inf = grub_net_add_addr (args[0], card, &addr, &card->default_address,
960
grub_net_add_ipv4_local (inf, -1);
966
grub_cmd_delroute (struct grub_command *cmd __attribute__ ((unused)),
967
int argc, char **args)
969
struct grub_net_route *route;
970
struct grub_net_route **prev;
973
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
975
for (prev = &grub_net_routes, route = *prev; route; prev = &((*prev)->next),
977
if (grub_strcmp (route->name, args[0]) == 0)
980
grub_free (route->name);
986
return GRUB_ERR_NONE;
990
grub_net_add_route (const char *name,
991
grub_net_network_level_netaddress_t target,
992
struct grub_net_network_level_interface *inter)
994
struct grub_net_route *route;
996
route = grub_zalloc (sizeof (*route));
1000
route->name = grub_strdup (name);
1007
route->target = target;
1008
route->is_gateway = 0;
1009
route->interface = inter;
1011
grub_net_route_register (route);
1013
return GRUB_ERR_NONE;
1017
grub_net_add_route_gw (const char *name,
1018
grub_net_network_level_netaddress_t target,
1019
grub_net_network_level_address_t gw)
1021
struct grub_net_route *route;
1023
route = grub_zalloc (sizeof (*route));
1027
route->name = grub_strdup (name);
1034
route->target = target;
1035
route->is_gateway = 1;
1038
grub_net_route_register (route);
1040
return GRUB_ERR_NONE;
1044
grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)),
1045
int argc, char **args)
1047
grub_net_network_level_netaddress_t target;
1049
return grub_error (GRUB_ERR_BAD_ARGUMENT,
1050
N_("three arguments expected"));
1052
grub_net_resolve_net_address (args[1], &target);
1054
if (grub_strcmp (args[2], "gw") == 0 && argc >= 4)
1057
grub_net_network_level_address_t gw;
1059
err = grub_net_resolve_address (args[3], &gw);
1062
return grub_net_add_route_gw (args[0], target, gw);
1066
struct grub_net_network_level_interface *inter;
1068
FOR_NET_NETWORK_LEVEL_INTERFACES (inter)
1069
if (grub_strcmp (inter->name, args[2]) == 0)
1073
return grub_error (GRUB_ERR_BAD_ARGUMENT,
1074
N_("unrecognised network interface `%s'"), args[2]);
1075
return grub_net_add_route (args[0], target, inter);
1080
print_net_address (const grub_net_network_level_netaddress_t *target)
1082
switch (target->type)
1084
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
1085
/* TRANSLATORS: it refers to the network address. */
1086
grub_printf ("%s\n", _("temporary"));
1088
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
1090
grub_uint32_t n = grub_be_to_cpu32 (target->ipv4.base);
1091
grub_printf ("%d.%d.%d.%d/%d ", ((n >> 24) & 0xff),
1095
target->ipv4.masksize);
1098
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
1100
char buf[GRUB_NET_MAX_STR_ADDR_LEN];
1101
struct grub_net_network_level_address base;
1102
base.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
1103
grub_memcpy (&base.ipv6, &target->ipv6, 16);
1104
grub_net_addr_to_str (&base, buf);
1105
grub_printf ("%s/%d ", buf, target->ipv6.masksize);
1109
grub_printf (_("Unknown address type %d\n"), target->type);
1113
print_address (const grub_net_network_level_address_t *target)
1115
char buf[GRUB_NET_MAX_STR_ADDR_LEN];
1116
grub_net_addr_to_str (target, buf);
1121
grub_cmd_listroutes (struct grub_command *cmd __attribute__ ((unused)),
1122
int argc __attribute__ ((unused)),
1123
char **args __attribute__ ((unused)))
1125
struct grub_net_route *route;
1126
FOR_NET_ROUTES(route)
1128
grub_printf ("%s ", route->name);
1129
print_net_address (&route->target);
1130
if (route->is_gateway)
1132
grub_printf ("gw ");
1133
print_address (&route->gw);
1136
grub_printf ("%s", route->interface->name);
1139
return GRUB_ERR_NONE;
1143
grub_cmd_listcards (struct grub_command *cmd __attribute__ ((unused)),
1144
int argc __attribute__ ((unused)),
1145
char **args __attribute__ ((unused)))
1147
struct grub_net_card *card;
1150
char buf[GRUB_NET_MAX_STR_HWADDR_LEN];
1151
grub_net_hwaddr_to_str (&card->default_address, buf);
1152
grub_printf ("%s %s\n", card->name, buf);
1154
return GRUB_ERR_NONE;
1158
grub_cmd_listaddrs (struct grub_command *cmd __attribute__ ((unused)),
1159
int argc __attribute__ ((unused)),
1160
char **args __attribute__ ((unused)))
1162
struct grub_net_network_level_interface *inf;
1163
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
1165
char bufh[GRUB_NET_MAX_STR_HWADDR_LEN];
1166
char bufn[GRUB_NET_MAX_STR_ADDR_LEN];
1167
grub_net_hwaddr_to_str (&inf->hwaddress, bufh);
1168
grub_net_addr_to_str (&inf->address, bufn);
1169
grub_printf ("%s %s %s\n", inf->name, bufh, bufn);
1171
return GRUB_ERR_NONE;
1174
grub_net_app_level_t grub_net_app_level_list;
1175
struct grub_net_socket *grub_net_sockets;
1178
grub_net_open_real (const char *name)
1180
grub_net_app_level_t proto;
1181
const char *protname, *server;
1182
grub_size_t protnamelen;
1184
if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0)
1187
protnamelen = sizeof ("tftp") - 1;
1188
server = name + sizeof ("pxe:") - 1;
1190
else if (grub_strcmp (name, "pxe") == 0)
1193
protnamelen = sizeof ("tftp") - 1;
1194
server = grub_net_default_server;
1199
comma = grub_strchr (name, ',');
1202
protnamelen = comma - name;
1208
protnamelen = grub_strlen (name);
1209
server = grub_net_default_server;
1215
grub_error (GRUB_ERR_NET_BAD_ADDRESS,
1216
N_("no server is specified"));
1220
FOR_NET_APP_LEVEL (proto)
1222
if (grub_memcmp (proto->name, protname, protnamelen) == 0
1223
&& proto->name[protnamelen] == 0)
1225
grub_net_t ret = grub_zalloc (sizeof (*ret));
1228
ret->protocol = proto;
1231
ret->server = grub_strdup (server);
1240
ret->fs = &grub_net_fs;
1247
/* Restore original error. */
1248
grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' not found"),
1255
grub_net_fs_dir (grub_device_t device, const char *path __attribute__ ((unused)),
1256
int (*hook) (const char *filename,
1257
const struct grub_dirhook_info *info) __attribute__ ((unused)))
1260
return grub_error (GRUB_ERR_BUG, "invalid net device");
1261
return GRUB_ERR_NONE;
1265
grub_net_fs_open (struct grub_file *file_out, const char *name)
1268
struct grub_file *file, *bufio;
1270
file = grub_malloc (sizeof (*file));
1274
grub_memcpy (file, file_out, sizeof (struct grub_file));
1275
file->device->net->packs.first = NULL;
1276
file->device->net->packs.last = NULL;
1277
file->device->net->name = grub_strdup (name);
1278
if (!file->device->net->name)
1281
err = file->device->net->protocol->open (file, name);
1284
while (file->device->net->packs.first)
1286
grub_netbuff_free (file->device->net->packs.first->nb);
1287
grub_net_remove_packet (file->device->net->packs.first);
1289
grub_free (file->device->net->name);
1293
bufio = grub_bufio_open (file, 32768);
1296
while (file->device->net->packs.first)
1298
grub_netbuff_free (file->device->net->packs.first->nb);
1299
grub_net_remove_packet (file->device->net->packs.first);
1301
file->device->net->protocol->close (file);
1302
grub_free (file->device->net->name);
1307
grub_memcpy (file_out, bufio, sizeof (struct grub_file));
1309
return GRUB_ERR_NONE;
1313
grub_net_fs_close (grub_file_t file)
1315
while (file->device->net->packs.first)
1317
grub_netbuff_free (file->device->net->packs.first->nb);
1318
grub_net_remove_packet (file->device->net->packs.first);
1320
file->device->net->protocol->close (file);
1321
grub_free (file->device->net->name);
1322
return GRUB_ERR_NONE;
1326
receive_packets (struct grub_net_card *card, int *stop_condition)
1329
if (card->num_ifaces == 0)
1333
grub_err_t err = GRUB_ERR_NONE;
1334
if (card->driver->open)
1335
err = card->driver->open (card);
1338
grub_errno = GRUB_ERR_NONE;
1345
/* Maybe should be better have a fixed number of packets for each card
1346
and just mark them as used and not used. */
1347
struct grub_net_buff *nb;
1349
if (received > 10 && stop_condition && *stop_condition)
1352
nb = card->driver->recv (card);
1355
card->last_poll = grub_get_time_ms ();
1359
grub_net_recv_ethernet_packet (nb, card);
1362
grub_dprintf ("net", "error receiving: %d: %s\n", grub_errno,
1364
grub_errno = GRUB_ERR_NONE;
1367
grub_print_error ();
1371
grub_net_poll_cards (unsigned time, int *stop_condition)
1373
struct grub_net_card *card;
1374
grub_uint64_t start_time;
1375
start_time = grub_get_time_ms ();
1376
while ((grub_get_time_ms () - start_time) < time
1377
&& (!stop_condition || !*stop_condition))
1378
FOR_NET_CARDS (card)
1379
receive_packets (card, stop_condition);
1380
grub_net_tcp_retransmit ();
1384
grub_net_poll_cards_idle_real (void)
1386
struct grub_net_card *card;
1387
FOR_NET_CARDS (card)
1389
grub_uint64_t ctime = grub_get_time_ms ();
1391
if (ctime < card->last_poll
1392
|| ctime >= card->last_poll + card->idle_poll_delay_ms)
1393
receive_packets (card, 0);
1395
grub_net_tcp_retransmit ();
1398
/* Read from the packets list*/
1400
grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len)
1402
grub_net_t net = file->device->net;
1403
struct grub_net_buff *nb;
1405
grub_size_t amount, total = 0;
1408
while (try <= GRUB_NET_TRIES)
1410
while (net->packs.first)
1413
nb = net->packs.first->nb;
1414
amount = nb->tail - nb->data;
1419
file->device->net->offset += amount;
1422
grub_memcpy (ptr, nb->data, amount);
1425
if (amount == (grub_size_t) (nb->tail - nb->data))
1427
grub_netbuff_free (nb);
1428
grub_net_remove_packet (net->packs.first);
1435
if (net->protocol->packets_pulled)
1436
net->protocol->packets_pulled (file);
1440
if (net->protocol->packets_pulled)
1441
net->protocol->packets_pulled (file);
1446
grub_net_poll_cards (GRUB_NET_INTERVAL, &net->stall);
1451
grub_error (GRUB_ERR_TIMEOUT, N_("timeout reading `%s'"), net->name);
1456
have_ahead (struct grub_file *file)
1458
grub_net_t net = file->device->net;
1459
grub_off_t ret = net->offset;
1460
struct grub_net_packet *pack;
1461
for (pack = net->packs.first; pack; pack = pack->next)
1462
ret += pack->nb->tail - pack->nb->data;
1467
grub_net_seek_real (struct grub_file *file, grub_off_t offset)
1469
if (offset == file->device->net->offset)
1470
return GRUB_ERR_NONE;
1472
if (offset > file->device->net->offset)
1474
if (!file->device->net->protocol->seek || have_ahead (file) >= offset)
1476
grub_net_fs_read_real (file, NULL,
1477
offset - file->device->net->offset);
1480
return file->device->net->protocol->seek (file, offset);
1485
if (file->device->net->protocol->seek)
1486
return file->device->net->protocol->seek (file, offset);
1487
while (file->device->net->packs.first)
1489
grub_netbuff_free (file->device->net->packs.first->nb);
1490
grub_net_remove_packet (file->device->net->packs.first);
1492
file->device->net->protocol->close (file);
1494
file->device->net->packs.first = NULL;
1495
file->device->net->packs.last = NULL;
1496
file->device->net->offset = 0;
1497
file->device->net->eof = 0;
1498
err = file->device->net->protocol->open (file, file->device->net->name);
1501
grub_net_fs_read_real (file, NULL, offset);
1507
grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
1509
if (file->offset != file->device->net->offset)
1512
err = grub_net_seek_real (file, file->offset);
1516
return grub_net_fs_read_real (file, buf, len);
1519
static struct grub_fs grub_net_fs =
1522
.dir = grub_net_fs_dir,
1523
.open = grub_net_fs_open,
1524
.read = grub_net_fs_read,
1525
.close = grub_net_fs_close,
1532
grub_net_fini_hw (int noreturn __attribute__ ((unused)))
1534
struct grub_net_card *card;
1535
FOR_NET_CARDS (card)
1538
if (card->driver->close)
1539
card->driver->close (card);
1542
return GRUB_ERR_NONE;
1546
grub_net_restore_hw (void)
1548
return GRUB_ERR_NONE;
1551
static struct grub_preboot *fini_hnd;
1553
static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute;
1554
static grub_command_t cmd_lsroutes, cmd_lscards;
1555
static grub_command_t cmd_lsaddr, cmd_slaac;
1559
grub_register_variable_hook ("net_default_server", defserver_get_env,
1561
grub_register_variable_hook ("pxe_default_server", defserver_get_env,
1564
cmd_addaddr = grub_register_command ("net_add_addr", grub_cmd_addaddr,
1565
/* TRANSLATORS: HWADDRESS stands for
1566
"hardware address". */
1567
N_("SHORTNAME CARD ADDRESS [HWADDRESS]"),
1568
N_("Add a network address."));
1569
cmd_slaac = grub_register_command ("net_ipv6_autoconf",
1570
grub_cmd_ipv6_autoconf,
1571
N_("[CARD [HWADDRESS]]"),
1572
N_("Perform an IPV6 autoconfiguration"));
1574
cmd_deladdr = grub_register_command ("net_del_addr", grub_cmd_deladdr,
1576
N_("Delete a network address."));
1577
cmd_addroute = grub_register_command ("net_add_route", grub_cmd_addroute,
1578
/* TRANSLATORS: "gw" is a keyword. */
1579
N_("SHORTNAME NET [INTERFACE| gw GATEWAY]"),
1580
N_("Add a network route."));
1581
cmd_delroute = grub_register_command ("net_del_route", grub_cmd_delroute,
1583
N_("Delete a network route."));
1584
cmd_lsroutes = grub_register_command ("net_ls_routes", grub_cmd_listroutes,
1585
"", N_("list network routes"));
1586
cmd_lscards = grub_register_command ("net_ls_cards", grub_cmd_listcards,
1587
"", N_("list network cards"));
1588
cmd_lsaddr = grub_register_command ("net_ls_addr", grub_cmd_listaddrs,
1589
"", N_("list network addresses"));
1593
grub_net_open = grub_net_open_real;
1594
fini_hnd = grub_loader_register_preboot_hook (grub_net_fini_hw,
1595
grub_net_restore_hw,
1596
GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
1597
grub_net_poll_cards_idle = grub_net_poll_cards_idle_real;
1602
grub_register_variable_hook ("net_default_server", 0, 0);
1603
grub_register_variable_hook ("pxe_default_server", 0, 0);
1607
grub_unregister_command (cmd_addaddr);
1608
grub_unregister_command (cmd_deladdr);
1609
grub_unregister_command (cmd_addroute);
1610
grub_unregister_command (cmd_delroute);
1611
grub_unregister_command (cmd_lsroutes);
1612
grub_unregister_command (cmd_lscards);
1613
grub_unregister_command (cmd_lsaddr);
1614
grub_unregister_command (cmd_slaac);
1615
grub_fs_unregister (&grub_net_fs);
1616
grub_net_open = NULL;
1617
grub_net_fini_hw (0);
1618
grub_loader_unregister_preboot_hook (fini_hnd);
1619
grub_net_poll_cards_idle = grub_net_poll_cards_idle_real;