From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1NMRQ9-0002fh-Eb for mharc-grub-devel@gnu.org; Sun, 20 Dec 2009 14:26:25 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NMRQ7-0002fT-CI for grub-devel@gnu.org; Sun, 20 Dec 2009 14:26:23 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NMRQ1-0002et-4Y for grub-devel@gnu.org; Sun, 20 Dec 2009 14:26:22 -0500 Received: from [199.232.76.173] (port=39305 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NMRQ1-0002eq-1L for grub-devel@gnu.org; Sun, 20 Dec 2009 14:26:17 -0500 Received: from mail-bw0-f215.google.com ([209.85.218.215]:58025) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NMRQ0-0000Bk-Bs for grub-devel@gnu.org; Sun, 20 Dec 2009 14:26:17 -0500 Received: by bwz7 with SMTP id 7so3379785bwz.26 for ; Sun, 20 Dec 2009 11:26:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from :user-agent:mime-version:to:subject:x-enigmail-version:content-type; bh=Q7puvGywzmEEgfPBBQxHdCblvDtpRFCba7MUTCsiv1o=; b=ThDpXxKmzC7PCGXC/xHmLzQAzPEDyCElBRMD17+241GlxqM4RsOc4XkTxcOCbxYTn5 pmKUm9DDlCzBrTWpOer4Np2mS+Br++sHvX+vJbh7dtxxoKOjc2S5ocZ+QYciWFzOGylb Uvs+e/eGDEuRxtTBRXcaIWq9quQW+0QCh794g= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:user-agent:mime-version:to:subject :x-enigmail-version:content-type; b=FCDpJdTPbPOTNZCNHxulf5ptgSj59LJE0g6P0wLzRFthtMWaREeUv0bnl3lzsVzOaA DULefgoP4NQB23GF+wCBYMoAvWCyIDJpMqk4T1tQtLTGByiqUfrd/w1Vf0lUJe8tL+nX ZwAAOHc2Z9qC5+8T4yyqzDpsTyZEhoJZgrs2Q= Received: by 10.204.163.68 with SMTP id z4mr375563bkx.86.1261337173984; Sun, 20 Dec 2009 11:26:13 -0800 (PST) Received: from debian.bg45.phnet ([81.62.161.118]) by mx.google.com with ESMTPS id 15sm1401485bwz.8.2009.12.20.11.26.12 (version=TLSv1/SSLv3 cipher=RC4-MD5); Sun, 20 Dec 2009 11:26:13 -0800 (PST) Message-ID: <4B2E7A49.5070901@gmail.com> Date: Sun, 20 Dec 2009 20:26:01 +0100 From: =?UTF-8?B?VmxhZGltaXIgJ8+GLWNvZGVyL3BoY29kZXInIFNlcmJpbmVua28=?= User-Agent: Mozilla-Thunderbird 2.0.0.22 (X11/20091109) MIME-Version: 1.0 To: The development of GRUB 2 X-Enigmail-Version: 0.95.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="------------enig7FEEDB6C61437A725EB335AF" X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 2) Subject: [PATCH] Add support for (pxe[:server_ip[:gateway_ip]]) and export pxe parameteres into grub environment X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 20 Dec 2009 19:26:24 -0000 This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enig7FEEDB6C61437A725EB335AF Content-Type: multipart/mixed; boundary="------------040706070802080706090501" This is a multi-part message in MIME format. --------------040706070802080706090501 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Any other DHCP options needed? --=20 Regards Vladimir '=CF=86-coder/phcoder' Serbinenko --------------040706070802080706090501 Content-Type: text/x-diff; name="pxeenv.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline; filename="pxeenv.diff" =3D=3D=3D added file 'ChangeLog.pxeenv' --- ChangeLog.pxeenv 1970-01-01 00:00:00 +0000 +++ ChangeLog.pxeenv 2009-12-20 19:23:11 +0000 @@ -0,0 +1,36 @@ +2009-12-19 Vladimir Serbinenko + + Support for (pxe[:server[:gateway]]) syntax and + use environment variable for PXE. + + * commands/i386/pc/pxecmd.c (options): Removed. + (print_ip): Removed. + (grub_cmd_pxe): Removed + (grub_cmd_pxe_unload): New function. + * fs/i386/pc/pxe.c (grub_pxe_disk_data): New structure. + (grub_pxe_your_ip): Made static. + (grub_pxe_default_server_ip): Likewise. + (grub_pxe_default_gateway_ip): Likewise. + (grub_pxe_blksize): Likewise. + (parse_ip): New function. + (grub_pxe_open): Support server and gateway specification. + (grub_pxe_close): Free disk->data. + (grub_pxefs_open): Use disk->data. + (grub_pxefs_read): Likewise. + (grub_env_write_readonly): New function. + (set_mac_env): Likewise. + (set_env_limn_ro): Likewise. + (parse_dhcp_vendor): Likewise. + (grub_pxe_detect): Set the environment variables. + (set_ip_env): New function. + (write_ip_env): Likewise. + (grub_env_write_pxe_default_server): Likewise. + (grub_env_write_pxe_default_gateway): Likewise. + (grub_env_write_pxe_blocksize): Likewise. + (GRUB_MOD_INIT(pxe)): Set environment variables. + * include/grub/i386/pc/pxe.h (grub_pxe_mac_addr): Rename to ... + (grub_pxe_mac_addr_t): ... this. All users updated. + (grub_pxe_your_ip): Removed. + (grub_pxe_server_ip): Likewise. + (grub_pxe_gateway_ip): Likewise. + (grub_pxe_blksize): Likewise. =3D=3D=3D modified file 'commands/i386/pc/pxecmd.c' --- commands/i386/pc/pxecmd.c 2009-05-04 03:49:08 +0000 +++ commands/i386/pc/pxecmd.c 2009-12-20 19:05:53 +0000 @@ -1,7 +1,7 @@ /* pxe.c - command to control the pxe driver */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2008 Free Software Foundation, Inc. + * Copyright (C) 2008,2009 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= @@ -21,79 +21,31 @@ #include #include #include -#include - -static const struct grub_arg_option options[] =3D -{ - {"info", 'i', 0, "show PXE information.", 0, 0}, - {"bsize", 'b', 0, "set PXE block size", 0, ARG_TYPE_INT}, - {"unload", 'u', 0, "unload PXE stack.", 0, 0}, - {0, 0, 0, 0, 0, 0} - }; - -static void -print_ip (grub_uint32_t ip) -{ - int i; - - for (i =3D 0; i < 3; i++) - { - grub_printf ("%d.", ip & 0xFF); - ip >>=3D 8; - } - grub_printf ("%d", ip); -} +#include =20 static grub_err_t -grub_cmd_pxe (grub_extcmd_t cmd, int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) +grub_cmd_pxe_unload (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) { - struct grub_arg_list *state =3D cmd->state; - if (! grub_pxe_pxenv) return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no pxe environment"); =20 - if (state[1].set) - { - int size; - - size =3D grub_strtoul (state[1].arg, 0, 0); - if (size < GRUB_PXE_MIN_BLKSIZE) - size =3D GRUB_PXE_MIN_BLKSIZE; - else if (size > GRUB_PXE_MAX_BLKSIZE) - size =3D GRUB_PXE_MAX_BLKSIZE; - - grub_pxe_blksize =3D size; - } - - if (state[0].set) - { - grub_printf ("blksize : %d\n", grub_pxe_blksize); - grub_printf ("client ip : "); - print_ip (grub_pxe_your_ip); - grub_printf ("\nserver ip : "); - print_ip (grub_pxe_server_ip); - grub_printf ("\ngateway ip : "); - print_ip (grub_pxe_gateway_ip); - grub_printf ("\n"); - } - - if (state[2].set) - grub_pxe_unload (); + grub_pxe_unload (); =20 return 0; } =20 -static grub_extcmd_t cmd; +static grub_command_t cmd; =20 GRUB_MOD_INIT(pxecmd) { - cmd =3D grub_register_extcmd ("pxe", grub_cmd_pxe, GRUB_COMMAND_FLAG_B= OTH, - "pxe [-i|-b|-u]", - "Command to control the PXE device.", options); + cmd =3D grub_register_command ("pxe_unload", grub_cmd_pxe_unload, + "pxe_unload", + "Unload PXE environment."); } =20 GRUB_MOD_FINI(pxecmd) { - grub_unregister_extcmd (cmd); + grub_unregister_command (cmd); } =3D=3D=3D modified file 'fs/i386/pc/pxe.c' --- fs/i386/pc/pxe.c 2009-12-20 13:09:16 +0000 +++ fs/i386/pc/pxe.c 2009-12-20 19:05:53 +0000 @@ -1,7 +1,7 @@ /* pxe.c - Driver to provide access to the pxe filesystem */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2008 Free Software Foundation, Inc. + * Copyright (C) 2008,2009 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= @@ -24,6 +24,7 @@ #include #include #include +#include =20 #include #include @@ -33,11 +34,17 @@ #define SEGOFS(x) ((SEGMENT(x) << 16) + OFFSET(x)) #define LINEAR(x) (void *) (((x >> 16) <<4) + (x & 0xFFFF)) =20 +struct grub_pxe_disk_data +{ + grub_uint32_t server_ip; + grub_uint32_t gateway_ip; +}; + struct grub_pxenv *grub_pxe_pxenv; -grub_uint32_t grub_pxe_your_ip; -grub_uint32_t grub_pxe_server_ip; -grub_uint32_t grub_pxe_gateway_ip; -int grub_pxe_blksize =3D GRUB_PXE_MIN_BLKSIZE; +static grub_uint32_t grub_pxe_your_ip; +static grub_uint32_t grub_pxe_default_server_ip; +static grub_uint32_t grub_pxe_default_gateway_ip; +static unsigned grub_pxe_blksize =3D GRUB_PXE_MIN_BLKSIZE; =20 static grub_file_t curr_file =3D 0; =20 @@ -57,23 +64,82 @@ grub_pxe_iterate (int (*hook) (const cha } =20 static grub_err_t +parse_ip (const char *val, grub_uint32_t *ip, const char **rest) +{ + grub_uint32_t newip =3D 0; + unsigned long t; + int i; + const char *ptr =3D val; + + for (i =3D 0; i < 4; i++) + { + t =3D grub_strtoul (ptr, (char **) &ptr, 0); + if (grub_errno) + return grub_errno; + if (t & ~0xff) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); + newip >>=3D 8; + newip |=3D (t << 24); + if (i !=3D 3 && *ptr !=3D '.') + return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); + ptr++; + } + *ip =3D newip; + if (rest) + *rest =3D ptr - 1; + return 0; +} + +static grub_err_t grub_pxe_open (const char *name, grub_disk_t disk) { - if (grub_strcmp (name, "pxe")) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a pxe disk"); + struct grub_pxe_disk_data *data; + + if (grub_strcmp (name, "pxe") !=3D 0 + && grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) !=3D 0) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a pxe disk"); + + data =3D grub_malloc (sizeof (*data)); + if (!data) + return grub_errno; + + if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) =3D=3D 0) + { + const char *ptr; + grub_err_t err; + + ptr =3D name + sizeof ("pxe:") - 1; + err =3D parse_ip (ptr, &(data->server_ip), &ptr); + if (err) + return err; + if (*ptr =3D=3D ':') + { + err =3D parse_ip (ptr + 1, &(data->server_ip), 0); + if (err) + return err; + } + else + data->gateway_ip =3D grub_pxe_default_gateway_ip; + } + else + { + data->server_ip =3D grub_pxe_default_server_ip; + data->gateway_ip =3D grub_pxe_default_gateway_ip; + } =20 disk->total_sectors =3D 0; - disk->id =3D (unsigned long) "pxe"; + disk->id =3D (unsigned long) data; =20 disk->has_partitions =3D 0; - disk->data =3D 0; + disk->data =3D data; =20 return GRUB_ERR_NONE; } =20 static void -grub_pxe_close (grub_disk_t disk __attribute((unused))) +grub_pxe_close (grub_disk_t disk) { + grub_free (disk->data); } =20 static grub_err_t @@ -125,6 +191,7 @@ grub_pxefs_open (struct grub_file *file, struct grub_pxenv_tftp_open c2; } c; struct grub_pxe_data *data; + struct grub_pxe_disk_data *disk_data =3D file->device->disk->data; grub_file_t file_int, bufio; =20 if (curr_file !=3D 0) @@ -133,8 +200,8 @@ grub_pxefs_open (struct grub_file *file, curr_file =3D 0; } =20 - c.c1.server_ip =3D grub_pxe_server_ip; - c.c1.gateway_ip =3D grub_pxe_gateway_ip; + c.c1.server_ip =3D disk_data->server_ip; + c.c1.gateway_ip =3D disk_data->gateway_ip; grub_strcpy ((char *)&c.c1.filename[0], name); grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1); if (c.c1.status) @@ -184,6 +251,7 @@ grub_pxefs_read (grub_file_t file, char=20 { struct grub_pxenv_tftp_read c; struct grub_pxe_data *data; + struct grub_pxe_disk_data *disk_data =3D file->device->disk->data; grub_uint32_t pn, r; =20 data =3D file->data; @@ -203,8 +271,8 @@ grub_pxefs_read (grub_file_t file, char=20 if (curr_file !=3D 0) grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &o); =20 - o.server_ip =3D grub_pxe_server_ip; - o.gateway_ip =3D grub_pxe_gateway_ip; + o.server_ip =3D disk_data->server_ip; + o.gateway_ip =3D disk_data->gateway_ip; grub_strcpy ((char *)&o.filename[0], data->filename); o.tftp_port =3D grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT); o.packet_size =3D grub_pxe_blksize; @@ -272,6 +340,99 @@ static struct grub_fs grub_pxefs_fs =3D .next =3D 0 }; =20 +static char * +grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused= )), + const char *val __attribute__ ((unused))) +{ + return NULL; +} + +static void +set_mac_env (grub_uint8_t *mac_addr, grub_size_t mac_len) +{ + char buf[(sizeof ("XX:") - 1) * mac_len + 1]; + char *ptr =3D buf; + unsigned i; + + for (i =3D 0; i < mac_len; i++) + { + grub_sprintf (ptr, "%02x:", mac_addr[i] & 0xff); + ptr +=3D (sizeof ("XX:") - 1); + } + if (mac_len) + *(ptr - 1) =3D 0; + else + buf[0] =3D 0; + + grub_env_set ("net_pxe_mac", buf); + /* XXX: Is it possible to change MAC in PXE? */ + grub_register_variable_hook ("net_pxe_mac", 0, grub_env_write_readonly= ); +} + +static void +set_env_limn_ro (const char *varname, char *value, grub_size_t len) +{ + char c; + c =3D value[len]; + value[len] =3D 0; + grub_env_set (varname, value); + value[len] =3D c; + grub_register_variable_hook (varname, 0, grub_env_write_readonly); +} + +static void +parse_dhcp_vendor (void *vend, int limit) +{ + grub_uint8_t *ptr, *ptr0; + + ptr =3D ptr0 =3D vend; + + if (grub_be_to_cpu32 (*(grub_uint32_t *) ptr) !=3D 0x63825363) + return; + ptr =3D ptr + sizeof (grub_uint32_t); + while (ptr - ptr0 < limit) + { + grub_uint8_t tagtype; + grub_uint8_t taglength; + + tagtype =3D *ptr++; + + /* Pad tag. */ + if (tagtype =3D=3D 0) + continue; + + /* End tag. */ + if (tagtype =3D=3D 0xff) + return; + + taglength =3D *ptr++; + + switch (tagtype) + { + case 12: + set_env_limn_ro ("net_pxe_hostname", (char *) ptr, taglength); + break; + + case 15: + set_env_limn_ro ("net_pxe_domain", (char *) ptr, taglength); + break; + + case 17: + set_env_limn_ro ("net_pxe_rootpath", (char *) ptr, taglength); + break; + + case 18: + set_env_limn_ro ("net_pxe_extensionspath", (char *) ptr, taglength); + break; + + /* If you need any other options please contact GRUB + developpement team. */ + } + + ptr +=3D taglength; + } +} + static void grub_pxe_detect (void) { @@ -293,9 +454,15 @@ grub_pxe_detect (void) bp =3D LINEAR (ci.buffer); =20 grub_pxe_your_ip =3D bp->your_ip; - grub_pxe_server_ip =3D bp->server_ip; - grub_pxe_gateway_ip =3D bp->gateway_ip; - + grub_pxe_default_server_ip =3D bp->server_ip; + grub_pxe_default_gateway_ip =3D bp->gateway_ip; + set_mac_env (bp->mac_addr, bp->hw_len < sizeof (bp->mac_addr) ? bp->hw= _len + : sizeof (bp->mac_addr)); + set_env_limn_ro ("net_pxe_boot_file", (char *) bp->boot_file, + sizeof (bp->boot_file)); + set_env_limn_ro ("net_pxe_dhcp_server_name", (char *) bp->server_name,= + sizeof (bp->server_name)); + parse_dhcp_vendor (&bp->vendor, sizeof (bp->vendor)); grub_pxe_pxenv =3D pxenv; } =20 @@ -311,11 +478,110 @@ grub_pxe_unload (void) } } =20 +static void +set_ip_env (char *varname, grub_uint32_t ip) +{ + char buf[sizeof ("XXX.XXX.XXX.XXX")]; + + grub_sprintf (buf, "%d.%d.%d.%d", (ip & 0xff), + (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff); + grub_env_set (varname, buf); +} + +static char * +write_ip_env (grub_uint32_t *ip, const char *val) +{ + char *buf; + grub_err_t err; + grub_uint32_t newip; + =20 + err =3D parse_ip (val, &newip, 0); + if (err) + return 0; + + /* Normalize the IP. */ + buf =3D grub_malloc (sizeof ("XXX.XXX.XXX.XXX")); + if (!buf) + return 0; + + *ip =3D newip; + + grub_sprintf (buf, "%d.%d.%d.%d", (newip & 0xff), (newip >> 8) & 0xff,= + (newip >> 16) & 0xff, (newip >> 24) & 0xff); + + return buf;=20 +} + +static char * +grub_env_write_pxe_default_server (struct grub_env_var *var=20 + __attribute__ ((unused)), + const char *val) +{ + return write_ip_env (&grub_pxe_default_server_ip, val); +} + +static char * +grub_env_write_pxe_default_gateway (struct grub_env_var *var + __attribute__ ((unused)), + const char *val) +{ + return write_ip_env (&grub_pxe_default_gateway_ip, val); +} + +static char * +grub_env_write_pxe_blocksize (struct grub_env_var *var __attribute__ ((u= nused)), + const char *val) +{ + unsigned size; + char *buf; + + size =3D grub_strtoul (val, 0, 0); + if (grub_errno) + return 0; + + if (size < GRUB_PXE_MIN_BLKSIZE) + size =3D GRUB_PXE_MIN_BLKSIZE; + else if (size > GRUB_PXE_MAX_BLKSIZE) + size =3D GRUB_PXE_MAX_BLKSIZE; + =20 + buf =3D grub_malloc (sizeof ("XXXXXX XXXXXX")); + if (!buf) + return 0; + + grub_sprintf (buf, "%d", size); + grub_pxe_blksize =3D size; + =20 + return buf; +} + + GRUB_MOD_INIT(pxe) { grub_pxe_detect (); if (grub_pxe_pxenv) { + char *buf; + + buf =3D grub_malloc (sizeof ("XXXXXX XXXXXX")); + if (buf) + { + grub_sprintf (buf, "%d", grub_pxe_blksize); + grub_env_set ("net_pxe_blksize", buf); + } + + set_ip_env ("pxe_default_server", grub_pxe_default_server_ip); + set_ip_env ("pxe_default_gateway", grub_pxe_default_gateway_ip); + set_ip_env ("net_pxe_ip", grub_pxe_your_ip); + grub_register_variable_hook ("net_pxe_default_server", 0, + grub_env_write_pxe_default_server); + grub_register_variable_hook ("net_pxe_default_gateway", 0, + grub_env_write_pxe_default_gateway); + + /* XXX: Is it possible to change IP in PXE? */ + grub_register_variable_hook ("net_pxe_ip", 0, + grub_env_write_readonly); + grub_register_variable_hook ("net_pxe_blksize", 0, + grub_env_write_pxe_blocksize); grub_disk_dev_register (&grub_pxe_dev); grub_fs_register (&grub_pxefs_fs); } =3D=3D=3D modified file 'include/grub/i386/pc/pxe.h' --- include/grub/i386/pc/pxe.h 2008-08-05 15:15:59 +0000 +++ include/grub/i386/pc/pxe.h 2009-12-20 19:05:53 +0000 @@ -201,7 +201,7 @@ struct grub_pxenv_get_cached_info =20 #define GRUB_PXE_MAC_ADDR_LEN 16 =20 -typedef grub_uint8_t grub_pxe_mac_addr[GRUB_PXE_MAC_ADDR_LEN]; +typedef grub_uint8_t grub_pxe_mac_addr_t[GRUB_PXE_MAC_ADDR_LEN]; =20 struct grub_pxenv_boot_player { @@ -216,7 +216,7 @@ struct grub_pxenv_boot_player grub_uint32_t your_ip; grub_uint32_t server_ip; grub_uint32_t gateway_ip; - grub_pxe_mac_addr mac_addr; + grub_pxe_mac_addr_t mac_addr; grub_uint8_t server_name[64]; grub_uint8_t boot_file[128]; union @@ -306,10 +306,6 @@ struct grub_pxenv * EXPORT_FUNC(grub_pxe int EXPORT_FUNC(grub_pxe_call) (int func, void * data); =20 extern struct grub_pxenv *grub_pxe_pxenv; -extern grub_uint32_t grub_pxe_your_ip; -extern grub_uint32_t grub_pxe_server_ip; -extern grub_uint32_t grub_pxe_gateway_ip; -extern int grub_pxe_blksize; =20 void grub_pxe_unload (void); =20 --------------040706070802080706090501-- --------------enig7FEEDB6C61437A725EB335AF Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iF4EAREKAAYFAksuelMACgkQNak7dOguQgmLTwEAuWmu4S3r3LmUtq9xMYzrZq+g 9+qDVZ//p3lIeRaCbbwA/RwDdKVUmJdpqtc+uq8lqnxcC15omU7hWuEWJ9JvdJC/ =a5/j -----END PGP SIGNATURE----- --------------enig7FEEDB6C61437A725EB335AF--