source: grub-pc/trunk/fuentes/grub-core/net/dns.c @ 22

Last change on this file since 22 was 22, checked in by mabarracus, 4 years ago

updated version and apply net.ifnames=0 into debian/rules

File size: 18.8 KB
Line 
1/*
2 *  GRUB  --  GRand Unified Bootloader
3 *  Copyright (C) 2010,2011  Free Software Foundation, Inc.
4 *
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.
9 *
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.
14 *
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/>.
17 */
18
19#include <grub/net.h>
20#include <grub/net/udp.h>
21#include <grub/command.h>
22#include <grub/i18n.h>
23#include <grub/err.h>
24#include <grub/time.h>
25
26struct dns_cache_element
27{
28  char *name;
29  grub_size_t naddresses;
30  struct grub_net_network_level_address *addresses;
31  grub_uint64_t limit_time;
32};
33
34#define DNS_CACHE_SIZE 1021
35#define DNS_HASH_BASE 423
36
37typedef enum grub_dns_qtype_id
38  {
39    GRUB_DNS_QTYPE_A = 1,
40    GRUB_DNS_QTYPE_AAAA = 28
41  } grub_dns_qtype_id_t;
42
43static struct dns_cache_element dns_cache[DNS_CACHE_SIZE];
44static struct grub_net_network_level_address *dns_servers;
45static grub_size_t dns_nservers, dns_servers_alloc;
46
47grub_err_t
48grub_net_add_dns_server (const struct grub_net_network_level_address *s)
49{
50  if (dns_servers_alloc <= dns_nservers)
51    {
52      int na = dns_servers_alloc * 2;
53      struct grub_net_network_level_address *ns;
54      if (na < 8)
55        na = 8;
56      ns = grub_realloc (dns_servers, na * sizeof (ns[0]));
57      if (!ns)
58        return grub_errno;
59      dns_servers_alloc = na;
60      dns_servers = ns;
61    }
62  dns_servers[dns_nservers++] = *s;
63  return GRUB_ERR_NONE;
64}
65
66void
67grub_net_remove_dns_server (const struct grub_net_network_level_address *s)
68{
69  grub_size_t i;
70  for (i = 0; i < dns_nservers; i++)
71    if (grub_net_addr_cmp (s, &dns_servers[i]) == 0)
72      break;
73  if (i < dns_nservers)
74    {
75      dns_servers[i] = dns_servers[dns_nservers - 1];
76      dns_nservers--;
77    }
78}
79
80struct dns_header
81{
82  grub_uint16_t id;
83  grub_uint8_t flags;
84  grub_uint8_t ra_z_r_code;
85  grub_uint16_t qdcount;
86  grub_uint16_t ancount;
87  grub_uint16_t nscount;
88  grub_uint16_t arcount;
89} GRUB_PACKED;
90
91enum
92  {
93    FLAGS_RESPONSE = 0x80,
94    FLAGS_OPCODE = 0x78,
95    FLAGS_RD = 0x01
96  };
97
98enum
99  {
100    ERRCODE_MASK = 0x0f
101  };
102
103enum
104  {
105    DNS_PORT = 53
106  };
107
108struct recv_data
109{
110  grub_size_t *naddresses;
111  struct grub_net_network_level_address **addresses;
112  int cache;
113  grub_uint16_t id;
114  int dns_err;
115  char *name;
116  const char *oname;
117  int stop;
118};
119
120static inline int
121hash (const char *str)
122{
123  unsigned v = 0, xn = 1;
124  const char *ptr;
125  for (ptr = str; *ptr; )
126    {
127      v = (v + xn * *ptr);
128      xn = (DNS_HASH_BASE * xn) % DNS_CACHE_SIZE;
129      ptr++;
130      if (((ptr - str) & 0x3ff) == 0)
131        v %= DNS_CACHE_SIZE;
132    }
133  return v % DNS_CACHE_SIZE;
134}
135
136static int
137check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head,
138                 const grub_uint8_t *tail, const char *check_with,
139                 int *length, char *set)
140{
141  const char *readable_ptr = check_with;
142  const grub_uint8_t *ptr;
143  char *optr = set;
144  int bytes_processed = 0;
145  if (length)
146    *length = 0;
147  for (ptr = name_at; ptr < tail && bytes_processed < tail - head + 2; )
148    {
149      /* End marker.  */
150      if (!*ptr)
151        {
152          if (length && *length)
153            (*length)--;
154          if (optr && optr != set)
155            optr--;
156          if (optr)
157            *optr = 0;
158          return !readable_ptr || (*readable_ptr == 0);
159        }
160      if (*ptr & 0xc0)
161        {
162          bytes_processed += 2;
163          if (ptr + 1 >= tail)
164            return 0;
165          ptr = head + (((ptr[0] & 0x3f) << 8) | ptr[1]);
166          continue;
167        }
168      if (readable_ptr && grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0)
169        return 0;
170      if (grub_memchr (ptr + 1, 0, *ptr) 
171          || grub_memchr (ptr + 1, '.', *ptr))
172        return 0;
173      if (readable_ptr)
174        readable_ptr += *ptr;
175      if (readable_ptr && *readable_ptr != '.' && *readable_ptr != 0)
176        return 0;
177      bytes_processed += *ptr + 1;
178      if (length)
179        *length += *ptr + 1;
180      if (optr)
181        {
182          grub_memcpy (optr, ptr + 1, *ptr);
183          optr += *ptr;
184        }
185      if (optr)
186        *optr++ = '.';
187      if (readable_ptr && *readable_ptr)
188        readable_ptr++;
189      ptr += *ptr + 1;
190    }
191  return 0;
192}
193
194static int
195check_name (const grub_uint8_t *name_at, const grub_uint8_t *head,
196            const grub_uint8_t *tail, const char *check_with)
197{
198  return check_name_real (name_at, head, tail, check_with, NULL, NULL);
199}
200
201static char *
202get_name (const grub_uint8_t *name_at, const grub_uint8_t *head,
203          const grub_uint8_t *tail)
204{
205  int length;
206  char *ret;
207
208  if (!check_name_real (name_at, head, tail, NULL, &length, NULL))
209    return NULL;
210  ret = grub_malloc (length + 1);
211  if (!ret)
212    return NULL;
213  if (!check_name_real (name_at, head, tail, NULL, NULL, ret))
214    {
215      grub_free (ret);
216      return NULL;
217    }
218  return ret;
219}
220
221enum
222  {
223    DNS_CLASS_A = 1,
224    DNS_CLASS_CNAME = 5,
225    DNS_CLASS_AAAA = 28
226  };
227
228static grub_err_t
229recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)),
230           struct grub_net_buff *nb,
231           void *data_)
232{
233  struct dns_header *head;
234  struct recv_data *data = data_;
235  int i, j;
236  grub_uint8_t *ptr, *reparse_ptr;
237  int redirect_cnt = 0;
238  char *redirect_save = NULL;
239  grub_uint32_t ttl_all = ~0U;
240
241  head = (struct dns_header *) nb->data;
242  ptr = (grub_uint8_t *) (head + 1);
243  if (ptr >= nb->tail)
244    {
245      grub_netbuff_free (nb);
246      return GRUB_ERR_NONE;
247    }
248 
249  if (head->id != data->id)
250    {
251      grub_netbuff_free (nb);
252      return GRUB_ERR_NONE;
253    }
254  if (!(head->flags & FLAGS_RESPONSE) || (head->flags & FLAGS_OPCODE))
255    {
256      grub_netbuff_free (nb);
257      return GRUB_ERR_NONE;
258    }
259  if (head->ra_z_r_code & ERRCODE_MASK)
260    {
261      data->dns_err = 1;
262      grub_netbuff_free (nb);
263      return GRUB_ERR_NONE;
264    }
265  for (i = 0; i < grub_cpu_to_be16 (head->qdcount); i++)
266    {
267      if (ptr >= nb->tail)
268        {
269          grub_netbuff_free (nb);
270          return GRUB_ERR_NONE;
271        }
272      while (ptr < nb->tail && !((*ptr & 0xc0) || *ptr == 0))
273        ptr += *ptr + 1;
274      if (ptr < nb->tail && (*ptr & 0xc0))
275        ptr++;
276      ptr++;
277      ptr += 4;
278    }
279  *data->addresses = grub_malloc (sizeof ((*data->addresses)[0])
280                                 * grub_cpu_to_be16 (head->ancount));
281  if (!*data->addresses)
282    {
283      grub_errno = GRUB_ERR_NONE;
284      grub_netbuff_free (nb);
285      return GRUB_ERR_NONE;
286    }
287  reparse_ptr = ptr;
288 reparse:
289  for (i = 0, ptr = reparse_ptr; i < grub_cpu_to_be16 (head->ancount); i++)
290    {
291      int ignored = 0;
292      grub_uint8_t class;
293      grub_uint32_t ttl = 0;
294      grub_uint16_t length;
295      if (ptr >= nb->tail)
296        {
297          if (!*data->naddresses)
298            grub_free (*data->addresses);
299          return GRUB_ERR_NONE;
300        }
301      ignored = !check_name (ptr, nb->data, nb->tail, data->name);
302      while (ptr < nb->tail && !((*ptr & 0xc0) || *ptr == 0))
303        ptr += *ptr + 1;
304      if (ptr < nb->tail && (*ptr & 0xc0))
305        ptr++;
306      ptr++;
307      if (ptr + 10 >= nb->tail)
308        {
309          if (!*data->naddresses)
310            grub_free (*data->addresses);
311          grub_netbuff_free (nb);
312          return GRUB_ERR_NONE;
313        }
314      if (*ptr++ != 0)
315        ignored = 1;
316      class = *ptr++;
317      if (*ptr++ != 0)
318        ignored = 1;
319      if (*ptr++ != 1)
320        ignored = 1;
321      for (j = 0; j < 4; j++)
322        {
323          ttl <<= 8;
324          ttl |= *ptr++;
325        }
326      length = *ptr++ << 8;
327      length |= *ptr++;
328      if (ptr + length > nb->tail)
329        {
330          if (!*data->naddresses)
331            grub_free (*data->addresses);
332          grub_netbuff_free (nb);
333          return GRUB_ERR_NONE;
334        }
335      if (!ignored)
336        {
337          if (ttl_all > ttl)
338            ttl_all = ttl;
339          switch (class)
340            {
341            case DNS_CLASS_A:
342              if (length != 4)
343                break;
344              (*data->addresses)[*data->naddresses].type
345                = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
346              grub_memcpy (&(*data->addresses)[*data->naddresses].ipv4,
347                           ptr, 4);
348              (*data->naddresses)++;
349              data->stop = 1;
350              break;
351            case DNS_CLASS_AAAA:
352              if (length != 16)
353                break;
354              (*data->addresses)[*data->naddresses].type
355                = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
356              grub_memcpy (&(*data->addresses)[*data->naddresses].ipv6,
357                           ptr, 16);
358              (*data->naddresses)++;
359              data->stop = 1;
360              break;
361            case DNS_CLASS_CNAME:
362              if (!(redirect_cnt & (redirect_cnt - 1)))
363                {
364                  grub_free (redirect_save);
365                  redirect_save = data->name;
366                }
367              else
368                grub_free (data->name);
369              redirect_cnt++;
370              data->name = get_name (ptr, nb->data, nb->tail);
371              if (!data->name)
372                {
373                  data->dns_err = 1;
374                  grub_errno = 0;
375                  return GRUB_ERR_NONE;
376                }
377              grub_dprintf ("dns", "CNAME %s\n", data->name);
378              if (grub_strcmp (redirect_save, data->name) == 0)
379                {
380                  data->dns_err = 1;
381                  grub_free (redirect_save);
382                  return GRUB_ERR_NONE;
383                }
384              goto reparse;
385            }
386        }
387      ptr += length;
388    }
389  if (ttl_all && *data->naddresses && data->cache)
390    {
391      int h;
392      grub_dprintf ("dns", "caching for %d seconds\n", ttl_all);
393      h = hash (data->oname);
394      grub_free (dns_cache[h].name);
395      dns_cache[h].name = 0;
396      grub_free (dns_cache[h].addresses);
397      dns_cache[h].addresses = 0;
398      dns_cache[h].name = grub_strdup (data->oname);
399      dns_cache[h].naddresses = *data->naddresses;
400      dns_cache[h].addresses = grub_malloc (*data->naddresses
401                                            * sizeof (dns_cache[h].addresses[0]));
402      dns_cache[h].limit_time = grub_get_time_ms () + 1000 * ttl_all;
403      if (!dns_cache[h].addresses || !dns_cache[h].name)
404        {
405          grub_free (dns_cache[h].name);
406          dns_cache[h].name = 0;
407          grub_free (dns_cache[h].addresses);
408          dns_cache[h].addresses = 0;
409        }
410      grub_memcpy (dns_cache[h].addresses, *data->addresses,
411                   *data->naddresses
412                   * sizeof (dns_cache[h].addresses[0]));
413    }
414  grub_netbuff_free (nb);
415  grub_free (redirect_save);
416  return GRUB_ERR_NONE;
417}
418
419grub_err_t
420grub_net_dns_lookup (const char *name,
421                     const struct grub_net_network_level_address *servers,
422                     grub_size_t n_servers,
423                     grub_size_t *naddresses,
424                     struct grub_net_network_level_address **addresses,
425                     int cache)
426{
427  grub_size_t send_servers = 0;
428  grub_size_t i, j;
429  struct grub_net_buff *nb;
430  grub_net_udp_socket_t *sockets;
431  grub_uint8_t *optr;
432  const char *iptr;
433  struct dns_header *head;
434  static grub_uint16_t id = 1;
435  grub_uint8_t *qtypeptr;
436  grub_err_t err = GRUB_ERR_NONE;
437  struct recv_data data = {naddresses, addresses, cache,
438                           grub_cpu_to_be16 (id++), 0, 0, name, 0};
439  grub_uint8_t *nbd;
440  int have_server = 0;
441
442  if (!servers)
443    {
444      servers = dns_servers;
445      n_servers = dns_nservers;
446    }
447
448  if (!n_servers)
449    return grub_error (GRUB_ERR_BAD_ARGUMENT,
450                       N_("no DNS servers configured"));
451
452  *naddresses = 0;
453  if (cache)
454    {
455      int h;
456      h = hash (name);
457      if (dns_cache[h].name && grub_strcmp (dns_cache[h].name, name) == 0
458          && grub_get_time_ms () < dns_cache[h].limit_time)
459        {
460          grub_dprintf ("dns", "retrieved from cache\n");
461          *addresses = grub_malloc (dns_cache[h].naddresses
462                                    * sizeof ((*addresses)[0]));
463          if (!*addresses)
464            return grub_errno;
465          *naddresses = dns_cache[h].naddresses;
466          grub_memcpy (*addresses, dns_cache[h].addresses,
467                       dns_cache[h].naddresses
468                       * sizeof ((*addresses)[0]));
469          return GRUB_ERR_NONE;
470        }
471    }
472
473  sockets = grub_malloc (sizeof (sockets[0]) * n_servers);
474  if (!sockets)
475    return grub_errno;
476
477  data.name = grub_strdup (name);
478  if (!data.name)
479    {
480      grub_free (sockets);
481      return grub_errno;
482    }
483
484  nb = grub_netbuff_alloc (GRUB_NET_OUR_MAX_IP_HEADER_SIZE
485                           + GRUB_NET_MAX_LINK_HEADER_SIZE
486                           + GRUB_NET_UDP_HEADER_SIZE
487                           + sizeof (struct dns_header)
488                           + grub_strlen (name) + 2 + 4);
489  if (!nb)
490    {
491      grub_free (sockets);
492      grub_free (data.name);
493      return grub_errno;
494    }
495  grub_netbuff_reserve (nb, GRUB_NET_OUR_MAX_IP_HEADER_SIZE
496                        + GRUB_NET_MAX_LINK_HEADER_SIZE
497                        + GRUB_NET_UDP_HEADER_SIZE);
498  grub_netbuff_put (nb, sizeof (struct dns_header)
499                    + grub_strlen (name) + 2 + 4);
500  head = (struct dns_header *) nb->data;
501  optr = (grub_uint8_t *) (head + 1);
502  for (iptr = name; *iptr; )
503    {
504      const char *dot;
505      dot = grub_strchr (iptr, '.');
506      if (!dot)
507        dot = iptr + grub_strlen (iptr);
508      if ((dot - iptr) >= 64)
509        {
510          grub_free (sockets);
511          grub_free (data.name);
512          return grub_error (GRUB_ERR_BAD_ARGUMENT,
513                             N_("domain name component is too long"));
514        }
515      *optr = (dot - iptr);
516      optr++;
517      grub_memcpy (optr, iptr, dot - iptr);
518      optr += dot - iptr;
519      iptr = dot;
520      if (*iptr)
521        iptr++;
522    }
523  *optr++ = 0;
524
525  /* Type.  */
526  *optr++ = 0;
527  qtypeptr = optr++;
528
529  /* Class.  */
530  *optr++ = 0;
531  *optr++ = 1;
532
533  head->id = data.id;
534  head->flags = FLAGS_RD;
535  head->ra_z_r_code = 0;
536  head->qdcount = grub_cpu_to_be16_compile_time (1);
537  head->ancount = grub_cpu_to_be16_compile_time (0);
538  head->nscount = grub_cpu_to_be16_compile_time (0);
539  head->arcount = grub_cpu_to_be16_compile_time (0);
540
541  nbd = nb->data;
542
543  for (i = 0; i < n_servers * 4; i++)
544    {
545      /* Connect to a next server.  */
546      while (!(i & 1) && send_servers < n_servers)
547        {
548          sockets[send_servers] = grub_net_udp_open (servers[send_servers],
549                                                     DNS_PORT,
550                                                     recv_hook,
551                                                     &data);
552          send_servers++;
553          if (!sockets[send_servers - 1])
554            {
555              err = grub_errno;
556              grub_errno = GRUB_ERR_NONE;
557            }
558          else
559            {
560              have_server = 1;
561              break;
562            }
563        }
564      if (!have_server)
565        goto out;
566      if (*data.naddresses)
567        goto out;
568      for (j = 0; j < send_servers; j++)
569        {
570          grub_err_t err2;
571          if (!sockets[j])
572            continue;
573          nb->data = nbd;
574
575          grub_size_t t = 0;
576          do
577            {
578              if (servers[j].option == DNS_OPTION_IPV4 ||
579                 ((servers[j].option == DNS_OPTION_PREFER_IPV4) && (t++ == 0)) ||
580                 ((servers[j].option == DNS_OPTION_PREFER_IPV6) && (t++ == 1)))
581                *qtypeptr = GRUB_DNS_QTYPE_A;
582              else
583                *qtypeptr = GRUB_DNS_QTYPE_AAAA;
584
585              grub_dprintf ("dns", "QTYPE: %u QNAME: %s\n", *qtypeptr, name);
586
587              err2 = grub_net_send_udp_packet (sockets[j], nb);
588              if (err2)
589                {
590                  grub_errno = GRUB_ERR_NONE;
591                  err = err2;
592                }
593              if (*data.naddresses)
594                goto out;
595            }
596          while (t == 1);
597        }
598      grub_net_poll_cards (200, &data.stop);
599    }
600 out:
601  grub_free (data.name);
602  grub_netbuff_free (nb);
603  for (j = 0; j < send_servers; j++)
604    grub_net_udp_close (sockets[j]);
605 
606  grub_free (sockets);
607
608  if (*data.naddresses)
609    return GRUB_ERR_NONE;
610  if (data.dns_err)
611    return grub_error (GRUB_ERR_NET_NO_DOMAIN,
612                       N_("no DNS record found"));
613   
614  if (err)
615    {
616      grub_errno = err;
617      return err;
618    }
619  return grub_error (GRUB_ERR_TIMEOUT,
620                     N_("no DNS reply received"));
621}
622
623static grub_err_t
624grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)),
625                   int argc, char **args)
626{
627  grub_err_t err;
628  struct grub_net_network_level_address cmd_server;
629  struct grub_net_network_level_address *servers;
630  grub_size_t nservers, i, naddresses = 0;
631  struct grub_net_network_level_address *addresses = 0;
632  if (argc != 2 && argc != 1)
633    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
634  if (argc == 2)
635    {
636      err = grub_net_resolve_address (args[1], &cmd_server);
637      if (err)
638        return err;
639      servers = &cmd_server;
640      nservers = 1;
641    }
642  else
643    {
644      servers = dns_servers;
645      nservers = dns_nservers;
646    }
647
648  grub_net_dns_lookup (args[0], servers, nservers, &naddresses,
649                       &addresses, 0);
650
651  for (i = 0; i < naddresses; i++)
652    {
653      char buf[GRUB_NET_MAX_STR_ADDR_LEN];
654      grub_net_addr_to_str (&addresses[i], buf);
655      grub_printf ("%s\n", buf);
656    }
657  grub_free (addresses);
658  if (naddresses)
659    return GRUB_ERR_NONE;
660  return grub_error (GRUB_ERR_NET_NO_DOMAIN, N_("no DNS record found"));
661}
662
663static grub_err_t
664grub_cmd_list_dns (struct grub_command *cmd __attribute__ ((unused)),
665                   int argc __attribute__ ((unused)),
666                   char **args __attribute__ ((unused)))
667{
668  grub_size_t i;
669  const char *strtype = "";
670
671  for (i = 0; i < dns_nservers; i++)
672    {
673      switch (dns_servers[i].option)
674        {
675        case DNS_OPTION_IPV4:
676          strtype = _("only ipv4");
677          break;
678
679        case DNS_OPTION_IPV6:
680          strtype = _("only ipv6");
681          break;
682
683        case DNS_OPTION_PREFER_IPV4:
684          strtype = _("prefer ipv4");
685          break;
686
687        case DNS_OPTION_PREFER_IPV6:
688          strtype = _("prefer ipv6");
689          break;
690        }
691
692      char buf[GRUB_NET_MAX_STR_ADDR_LEN];
693      grub_net_addr_to_str (&dns_servers[i], buf);
694      grub_printf ("%s (%s)\n", buf, strtype);
695    }
696  return GRUB_ERR_NONE;
697}
698
699static grub_err_t
700grub_cmd_add_dns (struct grub_command *cmd __attribute__ ((unused)),
701                  int argc, char **args)
702{
703  grub_err_t err;
704  struct grub_net_network_level_address server;
705
706  if ((argc < 1) || (argc > 2))
707    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
708  else if (argc == 1)
709    server.option = DNS_OPTION_PREFER_IPV4;
710  else
711    {
712      if (grub_strcmp (args[1], "--only-ipv4") == 0)
713          server.option = DNS_OPTION_IPV4;
714      else if (grub_strcmp (args[1], "--only-ipv6") == 0)
715          server.option = DNS_OPTION_IPV6;
716      else if (grub_strcmp (args[1], "--prefer-ipv4") == 0)
717          server.option = DNS_OPTION_PREFER_IPV4;
718      else if (grub_strcmp (args[1], "--prefer-ipv6") == 0)
719          server.option = DNS_OPTION_PREFER_IPV6;
720      else
721        return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
722    }
723
724  err = grub_net_resolve_address (args[0], &server);
725  if (err)
726    return err;
727
728  return grub_net_add_dns_server (&server);
729}
730
731static grub_err_t
732grub_cmd_del_dns (struct grub_command *cmd __attribute__ ((unused)),
733                  int argc, char **args)
734{
735  grub_err_t err;
736  struct grub_net_network_level_address server;
737
738  if (argc != 1)
739    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
740  err = grub_net_resolve_address (args[1], &server);
741  if (err)
742    return err;
743
744  return grub_net_add_dns_server (&server);
745}
746
747static grub_command_t cmd, cmd_add, cmd_del, cmd_list;
748
749void
750grub_dns_init (void)
751{
752  cmd = grub_register_command ("net_nslookup", grub_cmd_nslookup,
753                               N_("ADDRESS DNSSERVER"),
754                               N_("Perform a DNS lookup"));
755  cmd_add = grub_register_command ("net_add_dns", grub_cmd_add_dns,
756                                   N_("DNSSERVER"),
757                                   N_("Add a DNS server"));
758  cmd_del = grub_register_command ("net_del_dns", grub_cmd_del_dns,
759                                   N_("DNSSERVER"),
760                                   N_("Remove a DNS server"));
761  cmd_list = grub_register_command ("net_ls_dns", grub_cmd_list_dns,
762                                   NULL, N_("List DNS servers"));
763}
764
765void
766grub_dns_fini (void)
767{
768  grub_unregister_command (cmd);
769  grub_unregister_command (cmd_add);
770  grub_unregister_command (cmd_del);
771  grub_unregister_command (cmd_list);
772}
Note: See TracBrowser for help on using the repository browser.