mirror of
https://github.com/danderson/netboot.git
synced 2025-08-18 21:21:20 +02:00
third_party: update ipxe.
This commit is contained in:
parent
d0f6cb0348
commit
bff529103e
2
third_party/ipxe/COMMIT-ID
vendored
2
third_party/ipxe/COMMIT-ID
vendored
@ -1 +1 @@
|
|||||||
c53a209a4253a99a18fe3a9330fd85c9ce2b91a6
|
2afd66eb55996500499eb3bcc39c66ff042679c8
|
||||||
|
6
third_party/ipxe/ipxe-bin.go
vendored
6
third_party/ipxe/ipxe-bin.go
vendored
File diff suppressed because one or more lines are too long
6
third_party/ipxe/src/config/config.c
vendored
6
third_party/ipxe/src/config/config.c
vendored
@ -182,12 +182,6 @@ REQUIRE_OBJECT ( efi_image );
|
|||||||
#ifdef IMAGE_SDI
|
#ifdef IMAGE_SDI
|
||||||
REQUIRE_OBJECT ( sdi );
|
REQUIRE_OBJECT ( sdi );
|
||||||
#endif
|
#endif
|
||||||
#ifdef IMAGE_PNM
|
|
||||||
REQUIRE_OBJECT ( pnm );
|
|
||||||
#endif
|
|
||||||
#ifdef IMAGE_PNG
|
|
||||||
REQUIRE_OBJECT ( png );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Drag in all requested commands
|
* Drag in all requested commands
|
||||||
|
39
third_party/ipxe/src/config/config_asn1.c
vendored
Normal file
39
third_party/ipxe/src/config/config_asn1.c
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* This program 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 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* You can also choose to distribute this program under the terms of
|
||||||
|
* the Unmodified Binary Distribution Licence (as given in the file
|
||||||
|
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
#include <config/general.h>
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* ASN.1 file format configuration
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
PROVIDE_REQUIRING_SYMBOL();
|
||||||
|
|
||||||
|
#ifdef IMAGE_DER
|
||||||
|
REQUIRE_OBJECT ( der );
|
||||||
|
#endif
|
||||||
|
#ifdef IMAGE_PEM
|
||||||
|
REQUIRE_OBJECT ( pem );
|
||||||
|
#endif
|
39
third_party/ipxe/src/config/config_pixbuf.c
vendored
Normal file
39
third_party/ipxe/src/config/config_pixbuf.c
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* This program 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 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* You can also choose to distribute this program under the terms of
|
||||||
|
* the Unmodified Binary Distribution Licence (as given in the file
|
||||||
|
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
#include <config/general.h>
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* Pixel buffer file format configuration
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
PROVIDE_REQUIRING_SYMBOL();
|
||||||
|
|
||||||
|
#ifdef IMAGE_PNM
|
||||||
|
REQUIRE_OBJECT ( pnm );
|
||||||
|
#endif
|
||||||
|
#ifdef IMAGE_PNG
|
||||||
|
REQUIRE_OBJECT ( png );
|
||||||
|
#endif
|
4
third_party/ipxe/src/config/general.h
vendored
4
third_party/ipxe/src/config/general.h
vendored
@ -111,7 +111,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
//#define IMAGE_EFI /* EFI image support */
|
//#define IMAGE_EFI /* EFI image support */
|
||||||
//#define IMAGE_SDI /* SDI image support */
|
//#define IMAGE_SDI /* SDI image support */
|
||||||
//#define IMAGE_PNM /* PNM image support */
|
//#define IMAGE_PNM /* PNM image support */
|
||||||
//#define IMAGE_PNG /* PNG image support */
|
#define IMAGE_PNG /* PNG image support */
|
||||||
|
#define IMAGE_DER /* DER image support */
|
||||||
|
#define IMAGE_PEM /* PEM image support */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Command-line commands to include
|
* Command-line commands to include
|
||||||
|
24
third_party/ipxe/src/core/image.c
vendored
24
third_party/ipxe/src/core/image.c
vendored
@ -481,27 +481,3 @@ int image_set_trust ( int require_trusted, int permanent ) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create pixel buffer from image
|
|
||||||
*
|
|
||||||
* @v image Image
|
|
||||||
* @v pixbuf Pixel buffer to fill in
|
|
||||||
* @ret rc Return status code
|
|
||||||
*/
|
|
||||||
int image_pixbuf ( struct image *image, struct pixel_buffer **pixbuf ) {
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
/* Check that this image can be used to create a pixel buffer */
|
|
||||||
if ( ! ( image->type && image->type->pixbuf ) )
|
|
||||||
return -ENOTSUP;
|
|
||||||
|
|
||||||
/* Try creating pixel buffer */
|
|
||||||
if ( ( rc = image->type->pixbuf ( image, pixbuf ) ) != 0 ) {
|
|
||||||
DBGC ( image, "IMAGE %s could not create pixel buffer: %s\n",
|
|
||||||
image->name, strerror ( rc ) );
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
32
third_party/ipxe/src/core/pixbuf.c
vendored
32
third_party/ipxe/src/core/pixbuf.c
vendored
@ -30,7 +30,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <ipxe/umalloc.h>
|
#include <ipxe/umalloc.h>
|
||||||
|
#include <ipxe/image.h>
|
||||||
#include <ipxe/pixbuf.h>
|
#include <ipxe/pixbuf.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,3 +84,33 @@ struct pixel_buffer * alloc_pixbuf ( unsigned int width, unsigned int height ) {
|
|||||||
err_alloc_pixbuf:
|
err_alloc_pixbuf:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create pixel buffer from image
|
||||||
|
*
|
||||||
|
* @v image Image
|
||||||
|
* @v pixbuf Pixel buffer to fill in
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
int image_pixbuf ( struct image *image, struct pixel_buffer **pixbuf ) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Check that this image can be used to create a pixel buffer */
|
||||||
|
if ( ! ( image->type && image->type->pixbuf ) )
|
||||||
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
/* Try creating pixel buffer */
|
||||||
|
if ( ( rc = image->type->pixbuf ( image, pixbuf ) ) != 0 ) {
|
||||||
|
DBGC ( image, "IMAGE %s could not create pixel buffer: %s\n",
|
||||||
|
image->name, strerror ( rc ) );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Drag in objects via image_pixbuf() */
|
||||||
|
REQUIRING_SYMBOL ( image_pixbuf );
|
||||||
|
|
||||||
|
/* Drag in pixel buffer image formats */
|
||||||
|
REQUIRE_OBJECT ( config_pixbuf );
|
||||||
|
5
third_party/ipxe/src/core/settings.c
vendored
5
third_party/ipxe/src/core/settings.c
vendored
@ -331,6 +331,7 @@ struct settings * autovivify_child_settings ( struct settings *parent,
|
|||||||
&new_child->autovivified.refcnt );
|
&new_child->autovivified.refcnt );
|
||||||
settings = &new_child->autovivified.generic.settings;
|
settings = &new_child->autovivified.generic.settings;
|
||||||
register_settings ( settings, parent, new_child->name );
|
register_settings ( settings, parent, new_child->name );
|
||||||
|
ref_put ( settings->refcnt );
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,6 +452,8 @@ static void reprioritise_settings ( struct settings *settings ) {
|
|||||||
tmp_priority = fetch_intz_setting ( tmp, &priority_setting );
|
tmp_priority = fetch_intz_setting ( tmp, &priority_setting );
|
||||||
if ( priority > tmp_priority )
|
if ( priority > tmp_priority )
|
||||||
break;
|
break;
|
||||||
|
if ( settings->order > tmp->order )
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
list_add_tail ( &settings->siblings, &tmp->siblings );
|
list_add_tail ( &settings->siblings, &tmp->siblings );
|
||||||
|
|
||||||
@ -1784,7 +1787,7 @@ const struct setting_type setting_type_ipv6 __setting_type = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** IPv6 settings scope */
|
/** IPv6 settings scope */
|
||||||
const struct settings_scope ipv6_scope;
|
const struct settings_scope dhcpv6_scope;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integer setting type indices
|
* Integer setting type indices
|
||||||
|
55
third_party/ipxe/src/crypto/asn1.c
vendored
55
third_party/ipxe/src/crypto/asn1.c
vendored
@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <ipxe/tables.h>
|
#include <ipxe/tables.h>
|
||||||
|
#include <ipxe/image.h>
|
||||||
#include <ipxe/asn1.h>
|
#include <ipxe/asn1.h>
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@ -86,6 +87,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
*
|
*
|
||||||
* @v cursor ASN.1 object cursor
|
* @v cursor ASN.1 object cursor
|
||||||
* @v type Expected type, or ASN1_ANY
|
* @v type Expected type, or ASN1_ANY
|
||||||
|
* @v extra Additional length not present within partial cursor
|
||||||
* @ret len Length of object body, or negative error
|
* @ret len Length of object body, or negative error
|
||||||
*
|
*
|
||||||
* The object cursor will be updated to point to the start of the
|
* The object cursor will be updated to point to the start of the
|
||||||
@ -93,7 +95,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
* the length of the object body (i.e. the number of bytes until the
|
* the length of the object body (i.e. the number of bytes until the
|
||||||
* following object tag, if any) is returned.
|
* following object tag, if any) is returned.
|
||||||
*/
|
*/
|
||||||
static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) {
|
int asn1_start ( struct asn1_cursor *cursor, unsigned int type, size_t extra ) {
|
||||||
unsigned int len_len;
|
unsigned int len_len;
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
|
|
||||||
@ -135,9 +137,9 @@ static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) {
|
|||||||
cursor->data++;
|
cursor->data++;
|
||||||
cursor->len--;
|
cursor->len--;
|
||||||
}
|
}
|
||||||
if ( cursor->len < len ) {
|
if ( ( cursor->len + extra ) < len ) {
|
||||||
DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
|
DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
|
||||||
cursor, len, cursor->len );
|
cursor, len, ( cursor->len + extra ) );
|
||||||
return -EINVAL_ASN1_LEN;
|
return -EINVAL_ASN1_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +160,7 @@ static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) {
|
|||||||
int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
|
int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
len = asn1_start ( cursor, type );
|
len = asn1_start ( cursor, type, 0 );
|
||||||
if ( len < 0 ) {
|
if ( len < 0 ) {
|
||||||
asn1_invalidate_cursor ( cursor );
|
asn1_invalidate_cursor ( cursor );
|
||||||
return len;
|
return len;
|
||||||
@ -185,7 +187,7 @@ int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
|
|||||||
int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) {
|
int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) {
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
len = asn1_start ( cursor, type );
|
len = asn1_start ( cursor, type, 0 );
|
||||||
if ( len < 0 )
|
if ( len < 0 )
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
@ -242,7 +244,7 @@ int asn1_shrink ( struct asn1_cursor *cursor, unsigned int type ) {
|
|||||||
|
|
||||||
/* Find end of object */
|
/* Find end of object */
|
||||||
memcpy ( &temp, cursor, sizeof ( temp ) );
|
memcpy ( &temp, cursor, sizeof ( temp ) );
|
||||||
len = asn1_start ( &temp, type );
|
len = asn1_start ( &temp, type, 0 );
|
||||||
if ( len < 0 ) {
|
if ( len < 0 ) {
|
||||||
asn1_invalidate_cursor ( cursor );
|
asn1_invalidate_cursor ( cursor );
|
||||||
return len;
|
return len;
|
||||||
@ -837,3 +839,44 @@ int asn1_wrap ( struct asn1_builder *builder, unsigned int type ) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract ASN.1 object from image
|
||||||
|
*
|
||||||
|
* @v image Image
|
||||||
|
* @v offset Offset within image
|
||||||
|
* @v cursor ASN.1 cursor to fill in
|
||||||
|
* @ret next Offset to next image, or negative error
|
||||||
|
*
|
||||||
|
* The caller is responsible for eventually calling free() on the
|
||||||
|
* allocated ASN.1 cursor.
|
||||||
|
*/
|
||||||
|
int image_asn1 ( struct image *image, size_t offset,
|
||||||
|
struct asn1_cursor **cursor ) {
|
||||||
|
int next;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
assert ( offset <= image->len );
|
||||||
|
|
||||||
|
/* Check that this image can be used to extract an ASN.1 object */
|
||||||
|
if ( ! ( image->type && image->type->asn1 ) )
|
||||||
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
/* Try creating ASN.1 cursor */
|
||||||
|
next = image->type->asn1 ( image, offset, cursor );
|
||||||
|
if ( next < 0 ) {
|
||||||
|
rc = next;
|
||||||
|
DBGC ( image, "IMAGE %s could not extract ASN.1 object: %s\n",
|
||||||
|
image->name, strerror ( rc ) );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Drag in objects via image_asn1() */
|
||||||
|
REQUIRING_SYMBOL ( image_asn1 );
|
||||||
|
|
||||||
|
/* Drag in ASN.1 image formats */
|
||||||
|
REQUIRE_OBJECT ( config_asn1 );
|
||||||
|
@ -172,12 +172,3 @@ struct command image_trust_commands[] __command = {
|
|||||||
.exec = imgverify_exec,
|
.exec = imgverify_exec,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Drag in objects via command list */
|
|
||||||
REQUIRING_SYMBOL ( image_trust_commands );
|
|
||||||
|
|
||||||
/* Drag in objects typically required for signature verification */
|
|
||||||
REQUIRE_OBJECT ( rsa );
|
|
||||||
REQUIRE_OBJECT ( md5 );
|
|
||||||
REQUIRE_OBJECT ( sha1 );
|
|
||||||
REQUIRE_OBJECT ( sha256 );
|
|
||||||
|
120
third_party/ipxe/src/image/der.c
vendored
Normal file
120
third_party/ipxe/src/image/der.c
vendored
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>.
|
||||||
|
*
|
||||||
|
* This program 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 2 of the
|
||||||
|
* License, or any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* You can also choose to distribute this program under the terms of
|
||||||
|
* the Unmodified Binary Distribution Licence (as given in the file
|
||||||
|
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ipxe/asn1.h>
|
||||||
|
#include <ipxe/der.h>
|
||||||
|
#include <ipxe/uaccess.h>
|
||||||
|
#include <ipxe/image.h>
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* DER-encoded ASN.1 data
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract ASN.1 object from image
|
||||||
|
*
|
||||||
|
* @v image DER image
|
||||||
|
* @v offset Offset within image
|
||||||
|
* @v cursor ASN.1 cursor to fill in
|
||||||
|
* @ret next Offset to next image, or negative error
|
||||||
|
*
|
||||||
|
* The caller is responsible for eventually calling free() on the
|
||||||
|
* allocated ASN.1 cursor.
|
||||||
|
*/
|
||||||
|
static int der_asn1 ( struct image *image, size_t offset __unused,
|
||||||
|
struct asn1_cursor **cursor ) {
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
/* Allocate cursor and data buffer */
|
||||||
|
*cursor = malloc ( sizeof ( **cursor ) + image->len );
|
||||||
|
if ( ! *cursor )
|
||||||
|
return -ENOMEM;
|
||||||
|
data = ( ( ( void * ) *cursor ) + sizeof ( **cursor ) );
|
||||||
|
|
||||||
|
/* Populate cursor and data buffer */
|
||||||
|
(*cursor)->data = data;
|
||||||
|
(*cursor)->len = image->len;
|
||||||
|
copy_from_user ( data, image->data, 0, image->len );
|
||||||
|
|
||||||
|
return image->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Probe DER image
|
||||||
|
*
|
||||||
|
* @v image DER image
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
static int der_probe ( struct image *image ) {
|
||||||
|
struct asn1_cursor cursor;
|
||||||
|
uint8_t buf[8];
|
||||||
|
size_t extra;
|
||||||
|
size_t total;
|
||||||
|
int len;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Sanity check: no realistic DER image can be smaller than this */
|
||||||
|
if ( image->len < sizeof ( buf ) )
|
||||||
|
return -ENOEXEC;
|
||||||
|
|
||||||
|
/* Prepare partial cursor */
|
||||||
|
cursor.data = buf;
|
||||||
|
cursor.len = sizeof ( buf );
|
||||||
|
copy_from_user ( buf, image->data, 0, sizeof ( buf ) );
|
||||||
|
extra = ( image->len - sizeof ( buf ) );
|
||||||
|
|
||||||
|
/* Get length of ASN.1 sequence */
|
||||||
|
len = asn1_start ( &cursor, ASN1_SEQUENCE, extra );
|
||||||
|
if ( len < 0 ) {
|
||||||
|
rc = len;
|
||||||
|
DBGC ( image, "DER %s is not valid ASN.1: %s\n",
|
||||||
|
image->name, strerror ( rc ) );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add length of tag and length bytes consumed by asn1_start() */
|
||||||
|
total = ( len + ( cursor.data - ( ( void * ) buf ) ) );
|
||||||
|
assert ( total <= image->len );
|
||||||
|
|
||||||
|
/* Check that image comprises a single well-formed ASN.1 object */
|
||||||
|
if ( total != image->len ) {
|
||||||
|
DBGC ( image, "DER %s is not single ASN.1\n", image->name );
|
||||||
|
return -ENOEXEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** DER image type */
|
||||||
|
struct image_type der_image_type __image_type ( PROBE_NORMAL ) = {
|
||||||
|
.name = "DER",
|
||||||
|
.probe = der_probe,
|
||||||
|
.asn1 = der_asn1,
|
||||||
|
};
|
208
third_party/ipxe/src/image/pem.c
vendored
Normal file
208
third_party/ipxe/src/image/pem.c
vendored
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>.
|
||||||
|
*
|
||||||
|
* This program 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 2 of the
|
||||||
|
* License, or any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* You can also choose to distribute this program under the terms of
|
||||||
|
* the Unmodified Binary Distribution Licence (as given in the file
|
||||||
|
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ipxe/asn1.h>
|
||||||
|
#include <ipxe/pem.h>
|
||||||
|
#include <ipxe/base64.h>
|
||||||
|
#include <ipxe/uaccess.h>
|
||||||
|
#include <ipxe/image.h>
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* PEM-encoded ASN.1 data
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locate next line
|
||||||
|
*
|
||||||
|
* @v image PEM image
|
||||||
|
* @v offset Starting offset
|
||||||
|
* @ret next Offset to next line
|
||||||
|
*/
|
||||||
|
static size_t pem_next ( struct image *image, size_t offset ) {
|
||||||
|
off_t eol;
|
||||||
|
|
||||||
|
/* Find and skip next newline character, if any */
|
||||||
|
eol = memchr_user ( image->data, offset, '\n', ( image->len - offset ));
|
||||||
|
if ( eol < 0 )
|
||||||
|
return image->len;
|
||||||
|
return ( eol + 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locate boundary marker line
|
||||||
|
*
|
||||||
|
* @v image PEM image
|
||||||
|
* @v offset Starting offset
|
||||||
|
* @v marker Boundary marker
|
||||||
|
* @ret offset Offset to boundary marker line, or negative error
|
||||||
|
*/
|
||||||
|
static int pem_marker ( struct image *image, size_t offset,
|
||||||
|
const char *marker ) {
|
||||||
|
char buf[ strlen ( marker ) ];
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
assert ( offset <= image->len );
|
||||||
|
|
||||||
|
/* Scan for marker at start of line */
|
||||||
|
while ( offset < image->len ) {
|
||||||
|
|
||||||
|
/* Check for marker */
|
||||||
|
if ( ( image->len - offset ) < sizeof ( buf ) )
|
||||||
|
break;
|
||||||
|
copy_from_user ( buf, image->data, offset, sizeof ( buf ) );
|
||||||
|
if ( memcmp ( buf, marker, sizeof ( buf ) ) == 0 )
|
||||||
|
return offset;
|
||||||
|
|
||||||
|
/* Move to next line */
|
||||||
|
offset = pem_next ( image, offset );
|
||||||
|
assert ( offset <= image->len );
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract ASN.1 object from image
|
||||||
|
*
|
||||||
|
* @v image PEM image
|
||||||
|
* @v offset Offset within image
|
||||||
|
* @v cursor ASN.1 cursor to fill in
|
||||||
|
* @ret next Offset to next image, or negative error
|
||||||
|
*
|
||||||
|
* The caller is responsible for eventually calling free() on the
|
||||||
|
* allocated ASN.1 cursor.
|
||||||
|
*/
|
||||||
|
static int pem_asn1 ( struct image *image, size_t offset,
|
||||||
|
struct asn1_cursor **cursor ) {
|
||||||
|
size_t encoded_len;
|
||||||
|
size_t decoded_max_len;
|
||||||
|
char *encoded;
|
||||||
|
void *decoded;
|
||||||
|
int begin;
|
||||||
|
int end;
|
||||||
|
int len;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Locate and skip BEGIN marker */
|
||||||
|
begin = pem_marker ( image, offset, PEM_BEGIN );
|
||||||
|
if ( begin < 0 ) {
|
||||||
|
rc = begin;
|
||||||
|
DBGC ( image, "PEM %s [%#zx,%#zx) missing BEGIN marker: %s\n",
|
||||||
|
image->name, offset, image->len, strerror ( rc ) );
|
||||||
|
goto err_begin;
|
||||||
|
}
|
||||||
|
begin = pem_next ( image, begin );
|
||||||
|
|
||||||
|
/* Locate and skip END marker */
|
||||||
|
end = pem_marker ( image, begin, PEM_END );
|
||||||
|
if ( end < 0 ) {
|
||||||
|
rc = end;
|
||||||
|
DBGC ( image, "PEM %s [%#zx,%#zx) missing END marker: %s\n",
|
||||||
|
image->name, offset, image->len, strerror ( rc ) );
|
||||||
|
goto err_end;
|
||||||
|
}
|
||||||
|
encoded_len = ( end - begin );
|
||||||
|
end = pem_next ( image, end );
|
||||||
|
|
||||||
|
/* Extract Base64-encoded data */
|
||||||
|
encoded = malloc ( encoded_len + 1 /* NUL */ );
|
||||||
|
if ( ! encoded ) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto err_alloc_encoded;
|
||||||
|
}
|
||||||
|
copy_from_user ( encoded, image->data, begin, encoded_len );
|
||||||
|
encoded[encoded_len] = '\0';
|
||||||
|
|
||||||
|
/* Allocate cursor and data buffer */
|
||||||
|
decoded_max_len = base64_decoded_max_len ( encoded );
|
||||||
|
*cursor = malloc ( sizeof ( **cursor ) + decoded_max_len );
|
||||||
|
if ( ! *cursor ) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto err_alloc_decoded;
|
||||||
|
}
|
||||||
|
decoded = ( ( ( void * ) *cursor ) + sizeof ( **cursor ) );
|
||||||
|
|
||||||
|
/* Decode Base64-encoded data */
|
||||||
|
len = base64_decode ( encoded, decoded, decoded_max_len );
|
||||||
|
if ( len < 0 ) {
|
||||||
|
rc = len;
|
||||||
|
DBGC ( image, "PEM %s could not decode: %s\n",
|
||||||
|
image->name, strerror ( rc ) );
|
||||||
|
goto err_decode;
|
||||||
|
}
|
||||||
|
(*cursor)->data = decoded;
|
||||||
|
(*cursor)->len = len;
|
||||||
|
assert ( (*cursor)->len <= decoded_max_len );
|
||||||
|
|
||||||
|
/* Free Base64-encoded data */
|
||||||
|
free ( encoded );
|
||||||
|
|
||||||
|
/* Update offset and skip any unencapsulated trailer */
|
||||||
|
offset = end;
|
||||||
|
if ( pem_marker ( image, offset, PEM_BEGIN ) < 0 )
|
||||||
|
offset = image->len;
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
|
||||||
|
err_decode:
|
||||||
|
free ( decoded );
|
||||||
|
err_alloc_decoded:
|
||||||
|
free ( encoded );
|
||||||
|
err_alloc_encoded:
|
||||||
|
err_end:
|
||||||
|
err_begin:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Probe PEM image
|
||||||
|
*
|
||||||
|
* @v image PEM image
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
static int pem_probe ( struct image *image ) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Check that image contains a BEGIN marker */
|
||||||
|
if ( ( rc = pem_marker ( image, 0, PEM_BEGIN ) ) < 0 ) {
|
||||||
|
DBGC ( image, "PEM %s has no BEGIN marker: %s\n",
|
||||||
|
image->name, strerror ( rc ) );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** PEM image type */
|
||||||
|
struct image_type pem_image_type __image_type ( PROBE_NORMAL ) = {
|
||||||
|
.name = "PEM",
|
||||||
|
.probe = pem_probe,
|
||||||
|
.asn1 = pem_asn1,
|
||||||
|
};
|
3
third_party/ipxe/src/include/ipxe/asn1.h
vendored
3
third_party/ipxe/src/include/ipxe/asn1.h
vendored
@ -337,7 +337,8 @@ asn1_type ( const struct asn1_cursor *cursor ) {
|
|||||||
return ( ( cursor->len >= sizeof ( *type ) ) ? *type : ASN1_END );
|
return ( ( cursor->len >= sizeof ( *type ) ) ? *type : ASN1_END );
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void asn1_invalidate_cursor ( struct asn1_cursor *cursor );
|
extern int asn1_start ( struct asn1_cursor *cursor, unsigned int type,
|
||||||
|
size_t extra );
|
||||||
extern int asn1_enter ( struct asn1_cursor *cursor, unsigned int type );
|
extern int asn1_enter ( struct asn1_cursor *cursor, unsigned int type );
|
||||||
extern int asn1_skip_if_exists ( struct asn1_cursor *cursor,
|
extern int asn1_skip_if_exists ( struct asn1_cursor *cursor,
|
||||||
unsigned int type );
|
unsigned int type );
|
||||||
|
16
third_party/ipxe/src/include/ipxe/der.h
vendored
Normal file
16
third_party/ipxe/src/include/ipxe/der.h
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef _IPXE_DER_H
|
||||||
|
#define _IPXE_DER_H
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* DER image format
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
#include <ipxe/image.h>
|
||||||
|
|
||||||
|
extern struct image_type der_image_type __image_type ( PROBE_NORMAL );
|
||||||
|
|
||||||
|
#endif /* _IPXE_DER_H */
|
2
third_party/ipxe/src/include/ipxe/device.h
vendored
2
third_party/ipxe/src/include/ipxe/device.h
vendored
@ -72,7 +72,7 @@ struct device_description {
|
|||||||
/** A hardware device */
|
/** A hardware device */
|
||||||
struct device {
|
struct device {
|
||||||
/** Name */
|
/** Name */
|
||||||
char name[32];
|
char name[40];
|
||||||
/** Driver name */
|
/** Driver name */
|
||||||
const char *driver_name;
|
const char *driver_name;
|
||||||
/** Device description */
|
/** Device description */
|
||||||
|
3
third_party/ipxe/src/include/ipxe/errfile.h
vendored
3
third_party/ipxe/src/include/ipxe/errfile.h
vendored
@ -70,6 +70,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
#define ERRFILE_ansicoldef ( ERRFILE_CORE | 0x001e0000 )
|
#define ERRFILE_ansicoldef ( ERRFILE_CORE | 0x001e0000 )
|
||||||
#define ERRFILE_fault ( ERRFILE_CORE | 0x001f0000 )
|
#define ERRFILE_fault ( ERRFILE_CORE | 0x001f0000 )
|
||||||
#define ERRFILE_blocktrans ( ERRFILE_CORE | 0x00200000 )
|
#define ERRFILE_blocktrans ( ERRFILE_CORE | 0x00200000 )
|
||||||
|
#define ERRFILE_pixbuf ( ERRFILE_CORE | 0x00210000 )
|
||||||
|
|
||||||
#define ERRFILE_eisa ( ERRFILE_DRIVER | 0x00000000 )
|
#define ERRFILE_eisa ( ERRFILE_DRIVER | 0x00000000 )
|
||||||
#define ERRFILE_isa ( ERRFILE_DRIVER | 0x00010000 )
|
#define ERRFILE_isa ( ERRFILE_DRIVER | 0x00010000 )
|
||||||
@ -276,6 +277,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
#define ERRFILE_embedded ( ERRFILE_IMAGE | 0x00050000 )
|
#define ERRFILE_embedded ( ERRFILE_IMAGE | 0x00050000 )
|
||||||
#define ERRFILE_pnm ( ERRFILE_IMAGE | 0x00060000 )
|
#define ERRFILE_pnm ( ERRFILE_IMAGE | 0x00060000 )
|
||||||
#define ERRFILE_png ( ERRFILE_IMAGE | 0x00070000 )
|
#define ERRFILE_png ( ERRFILE_IMAGE | 0x00070000 )
|
||||||
|
#define ERRFILE_der ( ERRFILE_IMAGE | 0x00080000 )
|
||||||
|
#define ERRFILE_pem ( ERRFILE_IMAGE | 0x00090000 )
|
||||||
|
|
||||||
#define ERRFILE_asn1 ( ERRFILE_OTHER | 0x00000000 )
|
#define ERRFILE_asn1 ( ERRFILE_OTHER | 0x00000000 )
|
||||||
#define ERRFILE_chap ( ERRFILE_OTHER | 0x00010000 )
|
#define ERRFILE_chap ( ERRFILE_OTHER | 0x00010000 )
|
||||||
|
16
third_party/ipxe/src/include/ipxe/image.h
vendored
16
third_party/ipxe/src/include/ipxe/image.h
vendored
@ -17,6 +17,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
|
|
||||||
struct uri;
|
struct uri;
|
||||||
struct pixel_buffer;
|
struct pixel_buffer;
|
||||||
|
struct asn1_cursor;
|
||||||
struct image_type;
|
struct image_type;
|
||||||
|
|
||||||
/** An executable image */
|
/** An executable image */
|
||||||
@ -99,6 +100,19 @@ struct image_type {
|
|||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
int ( * pixbuf ) ( struct image *image, struct pixel_buffer **pixbuf );
|
int ( * pixbuf ) ( struct image *image, struct pixel_buffer **pixbuf );
|
||||||
|
/**
|
||||||
|
* Extract ASN.1 object from image
|
||||||
|
*
|
||||||
|
* @v image Image
|
||||||
|
* @v offset Offset within image
|
||||||
|
* @v cursor ASN.1 cursor to fill in
|
||||||
|
* @ret next Offset to next image, or negative error
|
||||||
|
*
|
||||||
|
* The caller is responsible for eventually calling free() on
|
||||||
|
* the allocated ASN.1 cursor.
|
||||||
|
*/
|
||||||
|
int ( * asn1 ) ( struct image *image, size_t offset,
|
||||||
|
struct asn1_cursor **cursor );
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -170,6 +184,8 @@ extern int image_select ( struct image *image );
|
|||||||
extern struct image * image_find_selected ( void );
|
extern struct image * image_find_selected ( void );
|
||||||
extern int image_set_trust ( int require_trusted, int permanent );
|
extern int image_set_trust ( int require_trusted, int permanent );
|
||||||
extern int image_pixbuf ( struct image *image, struct pixel_buffer **pixbuf );
|
extern int image_pixbuf ( struct image *image, struct pixel_buffer **pixbuf );
|
||||||
|
extern int image_asn1 ( struct image *image, size_t offset,
|
||||||
|
struct asn1_cursor **cursor );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increment reference count on an image
|
* Increment reference count on an image
|
||||||
|
8
third_party/ipxe/src/include/ipxe/in.h
vendored
8
third_party/ipxe/src/include/ipxe/in.h
vendored
@ -69,8 +69,12 @@ struct in6_addr {
|
|||||||
( ( *( ( const uint16_t * ) (addr) ) & htons ( 0xffc0 ) ) == \
|
( ( *( ( const uint16_t * ) (addr) ) & htons ( 0xffc0 ) ) == \
|
||||||
htons ( 0xfe80 ) )
|
htons ( 0xfe80 ) )
|
||||||
|
|
||||||
#define IN6_IS_ADDR_NONGLOBAL( addr ) \
|
#define IN6_IS_ADDR_SITELOCAL( addr ) \
|
||||||
( IN6_IS_ADDR_LINKLOCAL (addr) || IN6_IS_ADDR_MULTICAST (addr) )
|
( ( *( ( const uint16_t * ) (addr) ) & htons ( 0xffc0 ) ) == \
|
||||||
|
htons ( 0xfec0 ) )
|
||||||
|
|
||||||
|
#define IN6_IS_ADDR_ULA( addr ) \
|
||||||
|
( ( *( ( const uint8_t * ) (addr) ) & 0xfe ) == 0xfc )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IPv4 socket address
|
* IPv4 socket address
|
||||||
|
64
third_party/ipxe/src/include/ipxe/ipv6.h
vendored
64
third_party/ipxe/src/include/ipxe/ipv6.h
vendored
@ -25,6 +25,12 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
/** IPv6 maximum hop limit */
|
/** IPv6 maximum hop limit */
|
||||||
#define IPV6_HOP_LIMIT 0xff
|
#define IPV6_HOP_LIMIT 0xff
|
||||||
|
|
||||||
|
/** IPv6 default prefix length */
|
||||||
|
#define IPV6_DEFAULT_PREFIX_LEN 64
|
||||||
|
|
||||||
|
/** IPv6 maximum prefix length */
|
||||||
|
#define IPV6_MAX_PREFIX_LEN 128
|
||||||
|
|
||||||
/** IPv6 header */
|
/** IPv6 header */
|
||||||
struct ipv6_header {
|
struct ipv6_header {
|
||||||
/** Version (4 bits), Traffic class (8 bits), Flow label (20 bits) */
|
/** Version (4 bits), Traffic class (8 bits), Flow label (20 bits) */
|
||||||
@ -152,6 +158,24 @@ struct ipv6_pseudo_header {
|
|||||||
uint8_t next_header;
|
uint8_t next_header;
|
||||||
} __attribute__ (( packed ));
|
} __attribute__ (( packed ));
|
||||||
|
|
||||||
|
/** IPv6 address scopes */
|
||||||
|
enum ipv6_address_scope {
|
||||||
|
/** Interface-local address scope */
|
||||||
|
IPV6_SCOPE_INTERFACE_LOCAL = 0x1,
|
||||||
|
/** Link-local address scope */
|
||||||
|
IPV6_SCOPE_LINK_LOCAL = 0x2,
|
||||||
|
/** Admin-local address scope */
|
||||||
|
INV6_SCOPE_ADMIN_LOCAL = 0x4,
|
||||||
|
/** Site-local address scope */
|
||||||
|
IPV6_SCOPE_SITE_LOCAL = 0x5,
|
||||||
|
/** Organisation-local address scope */
|
||||||
|
IPV6_SCOPE_ORGANISATION_LOCAL = 0x8,
|
||||||
|
/** Global address scope */
|
||||||
|
IPV6_SCOPE_GLOBAL = 0xe,
|
||||||
|
/** Maximum scope */
|
||||||
|
IPV6_SCOPE_MAX = 0xf,
|
||||||
|
};
|
||||||
|
|
||||||
/** An IPv6 address/routing table entry */
|
/** An IPv6 address/routing table entry */
|
||||||
struct ipv6_miniroute {
|
struct ipv6_miniroute {
|
||||||
/** List of miniroutes */
|
/** List of miniroutes */
|
||||||
@ -168,6 +192,8 @@ struct ipv6_miniroute {
|
|||||||
struct in6_addr prefix_mask;
|
struct in6_addr prefix_mask;
|
||||||
/** Router address */
|
/** Router address */
|
||||||
struct in6_addr router;
|
struct in6_addr router;
|
||||||
|
/** Scope */
|
||||||
|
unsigned int scope;
|
||||||
/** Flags */
|
/** Flags */
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
};
|
};
|
||||||
@ -238,15 +264,45 @@ static inline void ipv6_all_routers ( struct in6_addr *addr ) {
|
|||||||
addr->s6_addr[15] = 2;
|
addr->s6_addr[15] = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get multicast address scope
|
||||||
|
*
|
||||||
|
* @v addr Multicast address
|
||||||
|
* @ret scope Address scope
|
||||||
|
*/
|
||||||
|
static inline unsigned int
|
||||||
|
ipv6_multicast_scope ( const struct in6_addr *addr ) {
|
||||||
|
|
||||||
|
return ( addr->s6_addr[1] & 0x0f );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** IPv6 settings sibling order */
|
||||||
|
enum ipv6_settings_order {
|
||||||
|
/** No address */
|
||||||
|
IPV6_ORDER_PREFIX_ONLY = -4,
|
||||||
|
/** Link-local address */
|
||||||
|
IPV6_ORDER_LINK_LOCAL = -3,
|
||||||
|
/** Address assigned via SLAAC */
|
||||||
|
IPV6_ORDER_SLAAC = -2,
|
||||||
|
/** Address assigned via DHCPv6 */
|
||||||
|
IPV6_ORDER_DHCPV6 = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** IPv6 link-local address settings block name */
|
||||||
|
#define IPV6_SETTINGS_NAME "link"
|
||||||
|
|
||||||
extern struct list_head ipv6_miniroutes;
|
extern struct list_head ipv6_miniroutes;
|
||||||
|
|
||||||
extern struct net_protocol ipv6_protocol __net_protocol;
|
extern struct net_protocol ipv6_protocol __net_protocol;
|
||||||
|
|
||||||
extern int ipv6_has_addr ( struct net_device *netdev, struct in6_addr *addr );
|
extern int ipv6_has_addr ( struct net_device *netdev, struct in6_addr *addr );
|
||||||
extern int ipv6_set_prefix ( struct net_device *netdev, struct in6_addr *prefix,
|
extern int ipv6_add_miniroute ( struct net_device *netdev,
|
||||||
unsigned int prefix_len, struct in6_addr *router );
|
struct in6_addr *address,
|
||||||
extern int ipv6_set_address ( struct net_device *netdev,
|
unsigned int prefix_len,
|
||||||
struct in6_addr *address );
|
struct in6_addr *router );
|
||||||
|
extern void ipv6_del_miniroute ( struct ipv6_miniroute *miniroute );
|
||||||
|
extern struct ipv6_miniroute * ipv6_route ( unsigned int scope_id,
|
||||||
|
struct in6_addr **dest );
|
||||||
extern int parse_ipv6_setting ( const struct setting_type *type,
|
extern int parse_ipv6_setting ( const struct setting_type *type,
|
||||||
const char *value, void *buf, size_t len );
|
const char *value, void *buf, size_t len );
|
||||||
extern int format_ipv6_setting ( const struct setting_type *type,
|
extern int format_ipv6_setting ( const struct setting_type *type,
|
||||||
|
22
third_party/ipxe/src/include/ipxe/pem.h
vendored
Normal file
22
third_party/ipxe/src/include/ipxe/pem.h
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef _IPXE_PEM_H
|
||||||
|
#define _IPXE_PEM_H
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* PEM image format
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
#include <ipxe/image.h>
|
||||||
|
|
||||||
|
/** Pre-encapsulation boundary marker */
|
||||||
|
#define PEM_BEGIN "-----BEGIN"
|
||||||
|
|
||||||
|
/** Post-encapsulation boundary marker */
|
||||||
|
#define PEM_END "-----END"
|
||||||
|
|
||||||
|
extern struct image_type pem_image_type __image_type ( PROBE_NORMAL );
|
||||||
|
|
||||||
|
#endif /* _IPXE_PEM_H */
|
49
third_party/ipxe/src/include/ipxe/settings.h
vendored
49
third_party/ipxe/src/include/ipxe/settings.h
vendored
@ -62,18 +62,22 @@ struct setting {
|
|||||||
|
|
||||||
#define SETTING_NETDEV 01 /**< Network device settings */
|
#define SETTING_NETDEV 01 /**< Network device settings */
|
||||||
#define SETTING_NETDEV_EXTRA 02 /**< Network device additional settings */
|
#define SETTING_NETDEV_EXTRA 02 /**< Network device additional settings */
|
||||||
#define SETTING_IP 03 /**< IPv4 settings */
|
#define SETTING_IP4 03 /**< IPv4 settings */
|
||||||
#define SETTING_IP_EXTRA 04 /**< IPv4 additional settings */
|
#define SETTING_IP4_EXTRA 04 /**< IPv4 additional settings */
|
||||||
#define SETTING_BOOT 05 /**< Generic boot settings */
|
#define SETTING_IP6 05 /**< IPv6 settings */
|
||||||
#define SETTING_BOOT_EXTRA 06 /**< Generic boot additional settings */
|
#define SETTING_IP6_EXTRA 06 /**< IPv6 additional settings */
|
||||||
#define SETTING_SANBOOT 07 /**< SAN boot settings */
|
#define SETTING_IP 07 /**< IPv4 settings */
|
||||||
#define SETTING_SANBOOT_EXTRA 08 /**< SAN boot additional settings */
|
#define SETTING_IP_EXTRA 08 /**< IPv4 additional settings */
|
||||||
#define SETTING_HOST 09 /**< Host identity settings */
|
#define SETTING_BOOT 09 /**< Generic boot settings */
|
||||||
#define SETTING_HOST_EXTRA 10 /**< Host identity additional settings */
|
#define SETTING_BOOT_EXTRA 10 /**< Generic boot additional settings */
|
||||||
#define SETTING_AUTH 11 /**< Authentication settings */
|
#define SETTING_SANBOOT 11 /**< SAN boot settings */
|
||||||
#define SETTING_AUTH_EXTRA 12 /**< Authentication additional settings */
|
#define SETTING_SANBOOT_EXTRA 12 /**< SAN boot additional settings */
|
||||||
#define SETTING_CRYPTO 13 /**< Cryptography settings */
|
#define SETTING_HOST 13 /**< Host identity settings */
|
||||||
#define SETTING_MISC 14 /**< Miscellaneous settings */
|
#define SETTING_HOST_EXTRA 14 /**< Host identity additional settings */
|
||||||
|
#define SETTING_AUTH 15 /**< Authentication settings */
|
||||||
|
#define SETTING_AUTH_EXTRA 16 /**< Authentication additional settings */
|
||||||
|
#define SETTING_CRYPTO 17 /**< Cryptography settings */
|
||||||
|
#define SETTING_MISC 18 /**< Miscellaneous settings */
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
@ -140,6 +144,8 @@ struct settings {
|
|||||||
struct settings_operations *op;
|
struct settings_operations *op;
|
||||||
/** Default scope for numerical settings constructed for this block */
|
/** Default scope for numerical settings constructed for this block */
|
||||||
const struct settings_scope *default_scope;
|
const struct settings_scope *default_scope;
|
||||||
|
/** Sibling ordering */
|
||||||
|
int order;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -280,7 +286,10 @@ struct builtin_setting {
|
|||||||
extern const struct settings_scope builtin_scope;
|
extern const struct settings_scope builtin_scope;
|
||||||
|
|
||||||
/** IPv6 setting scope */
|
/** IPv6 setting scope */
|
||||||
extern const struct settings_scope ipv6_scope;
|
extern const struct settings_scope ipv6_settings_scope;
|
||||||
|
|
||||||
|
/** DHCPv6 setting scope */
|
||||||
|
extern const struct settings_scope dhcpv6_scope;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A generic settings block
|
* A generic settings block
|
||||||
@ -421,13 +430,19 @@ extern const struct setting_type setting_type_busdevfn __setting_type;
|
|||||||
extern const struct setting_type setting_type_dnssl __setting_type;
|
extern const struct setting_type setting_type_dnssl __setting_type;
|
||||||
|
|
||||||
extern const struct setting
|
extern const struct setting
|
||||||
ip_setting __setting ( SETTING_IP, ip );
|
ip_setting __setting ( SETTING_IP4, ip );
|
||||||
extern const struct setting
|
extern const struct setting
|
||||||
netmask_setting __setting ( SETTING_IP, netmask );
|
netmask_setting __setting ( SETTING_IP4, netmask );
|
||||||
extern const struct setting
|
extern const struct setting
|
||||||
gateway_setting __setting ( SETTING_IP, gateway );
|
gateway_setting __setting ( SETTING_IP4, gateway );
|
||||||
extern const struct setting
|
extern const struct setting
|
||||||
dns_setting __setting ( SETTING_IP_EXTRA, dns );
|
dns_setting __setting ( SETTING_IP4_EXTRA, dns );
|
||||||
|
extern const struct setting
|
||||||
|
ip6_setting __setting ( SETTING_IP6, ip6 );
|
||||||
|
extern const struct setting
|
||||||
|
len6_setting __setting ( SETTING_IP6, len6 );
|
||||||
|
extern const struct setting
|
||||||
|
gateway6_setting __setting ( SETTING_IP6, gateway6 );
|
||||||
extern const struct setting
|
extern const struct setting
|
||||||
hostname_setting __setting ( SETTING_HOST, hostname );
|
hostname_setting __setting ( SETTING_HOST, hostname );
|
||||||
extern const struct setting
|
extern const struct setting
|
||||||
|
@ -1121,6 +1121,7 @@ static int vmbus_probe_channels ( struct hv_hypervisor *hv,
|
|||||||
const struct vmbus_message_header *header = &vmbus->message->header;
|
const struct vmbus_message_header *header = &vmbus->message->header;
|
||||||
const struct vmbus_offer_channel *offer = &vmbus->message->offer;
|
const struct vmbus_offer_channel *offer = &vmbus->message->offer;
|
||||||
const union uuid *type;
|
const union uuid *type;
|
||||||
|
union uuid instance;
|
||||||
struct vmbus_driver *driver;
|
struct vmbus_driver *driver;
|
||||||
struct vmbus_device *vmdev;
|
struct vmbus_device *vmdev;
|
||||||
struct vmbus_device *tmp;
|
struct vmbus_device *tmp;
|
||||||
@ -1165,8 +1166,11 @@ static int vmbus_probe_channels ( struct hv_hypervisor *hv,
|
|||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto err_alloc_vmdev;
|
goto err_alloc_vmdev;
|
||||||
}
|
}
|
||||||
|
memcpy ( &instance, &offer->instance,
|
||||||
|
sizeof ( instance ) );
|
||||||
|
uuid_mangle ( &instance );
|
||||||
snprintf ( vmdev->dev.name, sizeof ( vmdev->dev.name ),
|
snprintf ( vmdev->dev.name, sizeof ( vmdev->dev.name ),
|
||||||
"vmbus:%02x", channel );
|
"{%s}", uuid_ntoa ( &instance ) );
|
||||||
vmdev->dev.desc.bus_type = BUS_TYPE_HV;
|
vmdev->dev.desc.bus_type = BUS_TYPE_HV;
|
||||||
INIT_LIST_HEAD ( &vmdev->dev.children );
|
INIT_LIST_HEAD ( &vmdev->dev.children );
|
||||||
list_add_tail ( &vmdev->dev.siblings,
|
list_add_tail ( &vmdev->dev.siblings,
|
||||||
|
6
third_party/ipxe/src/net/ipv4.c
vendored
6
third_party/ipxe/src/net/ipv4.c
vendored
@ -788,7 +788,7 @@ int format_ipv4_setting ( const struct setting_type *type __unused,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** IPv4 address setting */
|
/** IPv4 address setting */
|
||||||
const struct setting ip_setting __setting ( SETTING_IP, ip ) = {
|
const struct setting ip_setting __setting ( SETTING_IP4, ip ) = {
|
||||||
.name = "ip",
|
.name = "ip",
|
||||||
.description = "IP address",
|
.description = "IP address",
|
||||||
.tag = DHCP_EB_YIADDR,
|
.tag = DHCP_EB_YIADDR,
|
||||||
@ -796,7 +796,7 @@ const struct setting ip_setting __setting ( SETTING_IP, ip ) = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** IPv4 subnet mask setting */
|
/** IPv4 subnet mask setting */
|
||||||
const struct setting netmask_setting __setting ( SETTING_IP, netmask ) = {
|
const struct setting netmask_setting __setting ( SETTING_IP4, netmask ) = {
|
||||||
.name = "netmask",
|
.name = "netmask",
|
||||||
.description = "Subnet mask",
|
.description = "Subnet mask",
|
||||||
.tag = DHCP_SUBNET_MASK,
|
.tag = DHCP_SUBNET_MASK,
|
||||||
@ -804,7 +804,7 @@ const struct setting netmask_setting __setting ( SETTING_IP, netmask ) = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** Default gateway setting */
|
/** Default gateway setting */
|
||||||
const struct setting gateway_setting __setting ( SETTING_IP, gateway ) = {
|
const struct setting gateway_setting __setting ( SETTING_IP4, gateway ) = {
|
||||||
.name = "gateway",
|
.name = "gateway",
|
||||||
.description = "Default gateway",
|
.description = "Default gateway",
|
||||||
.tag = DHCP_ROUTERS,
|
.tag = DHCP_ROUTERS,
|
||||||
|
509
third_party/ipxe/src/net/ipv6.c
vendored
509
third_party/ipxe/src/net/ipv6.c
vendored
@ -23,6 +23,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <byteswap.h>
|
#include <byteswap.h>
|
||||||
@ -78,6 +79,40 @@ static uint32_t ipv6col ( struct in6_addr *in ) {
|
|||||||
return crc32_le ( 0, in, sizeof ( *in ) );
|
return crc32_le ( 0, in, sizeof ( *in ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine IPv6 address scope
|
||||||
|
*
|
||||||
|
* @v addr IPv6 address
|
||||||
|
* @ret scope Address scope
|
||||||
|
*/
|
||||||
|
static unsigned int ipv6_scope ( const struct in6_addr *addr ) {
|
||||||
|
|
||||||
|
/* Multicast addresses directly include a scope field */
|
||||||
|
if ( IN6_IS_ADDR_MULTICAST ( addr ) )
|
||||||
|
return ipv6_multicast_scope ( addr );
|
||||||
|
|
||||||
|
/* Link-local addresses have link-local scope */
|
||||||
|
if ( IN6_IS_ADDR_LINKLOCAL ( addr ) )
|
||||||
|
return IPV6_SCOPE_LINK_LOCAL;
|
||||||
|
|
||||||
|
/* Site-local addresses have site-local scope */
|
||||||
|
if ( IN6_IS_ADDR_SITELOCAL ( addr ) )
|
||||||
|
return IPV6_SCOPE_SITE_LOCAL;
|
||||||
|
|
||||||
|
/* Unique local addresses do not directly map to a defined
|
||||||
|
* scope. They effectively have a scope which is wider than
|
||||||
|
* link-local but narrower than global. Since the only
|
||||||
|
* multicast packets that we transmit are link-local, we can
|
||||||
|
* simply choose an arbitrary scope between link-local and
|
||||||
|
* global.
|
||||||
|
*/
|
||||||
|
if ( IN6_IS_ADDR_ULA ( addr ) )
|
||||||
|
return IPV6_SCOPE_ORGANISATION_LOCAL;
|
||||||
|
|
||||||
|
/* All other addresses are assumed to be global */
|
||||||
|
return IPV6_SCOPE_GLOBAL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dump IPv6 routing table entry
|
* Dump IPv6 routing table entry
|
||||||
*
|
*
|
||||||
@ -119,23 +154,32 @@ int ipv6_has_addr ( struct net_device *netdev, struct in6_addr *addr ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if IPv6 address is within a routing table entry's local network
|
* Count matching bits of an IPv6 routing table entry prefix
|
||||||
*
|
*
|
||||||
* @v miniroute Routing table entry
|
* @v miniroute Routing table entry
|
||||||
* @v address IPv6 address
|
* @v address IPv6 address
|
||||||
* @ret is_on_link Address is within this entry's local network
|
* @ret match_len Number of matching prefix bits
|
||||||
*/
|
*/
|
||||||
static int ipv6_is_on_link ( struct ipv6_miniroute *miniroute,
|
static unsigned int ipv6_match_len ( struct ipv6_miniroute *miniroute,
|
||||||
struct in6_addr *address ) {
|
struct in6_addr *address ) {
|
||||||
|
unsigned int match_len = 0;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
uint32_t diff;
|
||||||
|
|
||||||
for ( i = 0 ; i < ( sizeof ( address->s6_addr32 ) /
|
for ( i = 0 ; i < ( sizeof ( address->s6_addr32 ) /
|
||||||
sizeof ( address->s6_addr32[0] ) ) ; i++ ) {
|
sizeof ( address->s6_addr32[0] ) ) ; i++ ) {
|
||||||
if ( (( address->s6_addr32[i] ^ miniroute->address.s6_addr32[i])
|
|
||||||
& miniroute->prefix_mask.s6_addr32[i] ) != 0 )
|
diff = ntohl ( ~( ( ~( address->s6_addr32[i] ^
|
||||||
return 0;
|
miniroute->address.s6_addr32[i] ) )
|
||||||
|
& miniroute->prefix_mask.s6_addr32[i] ) );
|
||||||
|
match_len += 32;
|
||||||
|
if ( diff ) {
|
||||||
|
match_len -= flsl ( diff );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return 1;
|
}
|
||||||
|
|
||||||
|
return match_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -148,13 +192,16 @@ static int ipv6_is_on_link ( struct ipv6_miniroute *miniroute,
|
|||||||
static struct ipv6_miniroute * ipv6_miniroute ( struct net_device *netdev,
|
static struct ipv6_miniroute * ipv6_miniroute ( struct net_device *netdev,
|
||||||
struct in6_addr *address ) {
|
struct in6_addr *address ) {
|
||||||
struct ipv6_miniroute *miniroute;
|
struct ipv6_miniroute *miniroute;
|
||||||
|
unsigned int match_len;
|
||||||
|
|
||||||
list_for_each_entry ( miniroute, &ipv6_miniroutes, list ) {
|
list_for_each_entry ( miniroute, &ipv6_miniroutes, list ) {
|
||||||
if ( ( miniroute->netdev == netdev ) &&
|
if ( miniroute->netdev != netdev )
|
||||||
ipv6_is_on_link ( miniroute, address ) ) {
|
continue;
|
||||||
|
match_len = ipv6_match_len ( miniroute, address );
|
||||||
|
if ( match_len < miniroute->prefix_len )
|
||||||
|
continue;
|
||||||
return miniroute;
|
return miniroute;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,107 +211,89 @@ static struct ipv6_miniroute * ipv6_miniroute ( struct net_device *netdev,
|
|||||||
* @v netdev Network device
|
* @v netdev Network device
|
||||||
* @v address IPv6 address (or prefix)
|
* @v address IPv6 address (or prefix)
|
||||||
* @v prefix_len Prefix length
|
* @v prefix_len Prefix length
|
||||||
* @v flags Flags
|
* @v router Router address (if any)
|
||||||
* @ret miniroute Routing table entry, or NULL on failure
|
|
||||||
*/
|
|
||||||
static struct ipv6_miniroute * ipv6_add_miniroute ( struct net_device *netdev,
|
|
||||||
struct in6_addr *address,
|
|
||||||
unsigned int prefix_len,
|
|
||||||
unsigned int flags ) {
|
|
||||||
struct ipv6_miniroute *miniroute;
|
|
||||||
uint8_t *prefix_mask;
|
|
||||||
|
|
||||||
/* Create routing table entry */
|
|
||||||
miniroute = zalloc ( sizeof ( *miniroute ) );
|
|
||||||
if ( ! miniroute )
|
|
||||||
return NULL;
|
|
||||||
miniroute->netdev = netdev_get ( netdev );
|
|
||||||
memcpy ( &miniroute->address, address, sizeof ( miniroute->address ) );
|
|
||||||
miniroute->prefix_len = prefix_len;
|
|
||||||
assert ( prefix_len <= ( 8 * sizeof ( miniroute->prefix_mask ) ) );
|
|
||||||
for ( prefix_mask = miniroute->prefix_mask.s6_addr ; prefix_len >= 8 ;
|
|
||||||
prefix_mask++, prefix_len -= 8 ) {
|
|
||||||
*prefix_mask = 0xff;
|
|
||||||
}
|
|
||||||
if ( prefix_len )
|
|
||||||
*prefix_mask <<= ( 8 - prefix_len );
|
|
||||||
miniroute->flags = flags;
|
|
||||||
list_add ( &miniroute->list, &ipv6_miniroutes );
|
|
||||||
ipv6_dump_miniroute ( miniroute );
|
|
||||||
|
|
||||||
return miniroute;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define IPv6 on-link prefix
|
|
||||||
*
|
|
||||||
* @v netdev Network device
|
|
||||||
* @v prefix IPv6 address prefix
|
|
||||||
* @v prefix_len Prefix length
|
|
||||||
* @v router Router address (or NULL)
|
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
int ipv6_set_prefix ( struct net_device *netdev, struct in6_addr *prefix,
|
int ipv6_add_miniroute ( struct net_device *netdev, struct in6_addr *address,
|
||||||
unsigned int prefix_len, struct in6_addr *router ) {
|
unsigned int prefix_len, struct in6_addr *router ) {
|
||||||
struct ipv6_miniroute *miniroute;
|
struct ipv6_miniroute *miniroute;
|
||||||
int changed;
|
uint8_t *prefix_mask;
|
||||||
|
unsigned int remaining;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
/* Find or create routing table entry */
|
/* Find or create routing table entry */
|
||||||
miniroute = ipv6_miniroute ( netdev, prefix );
|
miniroute = ipv6_miniroute ( netdev, address );
|
||||||
if ( ! miniroute )
|
if ( miniroute ) {
|
||||||
miniroute = ipv6_add_miniroute ( netdev, prefix, prefix_len, 0);
|
|
||||||
|
/* Remove from existing position in routing table */
|
||||||
|
list_del ( &miniroute->list );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Create new routing table entry */
|
||||||
|
miniroute = zalloc ( sizeof ( *miniroute ) );
|
||||||
if ( ! miniroute )
|
if ( ! miniroute )
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
miniroute->netdev = netdev_get ( netdev );
|
||||||
|
memcpy ( &miniroute->address, address,
|
||||||
|
sizeof ( miniroute->address ) );
|
||||||
|
|
||||||
/* Record router and add to start or end of list as appropriate */
|
/* Default to prefix length of 64 if none specified */
|
||||||
list_del ( &miniroute->list );
|
if ( ! prefix_len )
|
||||||
|
prefix_len = IPV6_DEFAULT_PREFIX_LEN;
|
||||||
|
miniroute->prefix_len = prefix_len;
|
||||||
|
assert ( prefix_len <= IPV6_MAX_PREFIX_LEN );
|
||||||
|
|
||||||
|
/* Construct prefix mask */
|
||||||
|
remaining = prefix_len;
|
||||||
|
for ( prefix_mask = miniroute->prefix_mask.s6_addr ;
|
||||||
|
remaining >= 8 ; prefix_mask++, remaining -= 8 ) {
|
||||||
|
*prefix_mask = 0xff;
|
||||||
|
}
|
||||||
|
if ( remaining )
|
||||||
|
*prefix_mask <<= ( 8 - remaining );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add to start of routing table */
|
||||||
|
list_add ( &miniroute->list, &ipv6_miniroutes );
|
||||||
|
|
||||||
|
/* Set or update address, if applicable */
|
||||||
|
for ( i = 0 ; i < ( sizeof ( address->s6_addr32 ) /
|
||||||
|
sizeof ( address->s6_addr32[0] ) ) ; i++ ) {
|
||||||
|
if ( ( address->s6_addr32[i] &
|
||||||
|
~miniroute->prefix_mask.s6_addr32[i] ) != 0 ) {
|
||||||
|
memcpy ( &miniroute->address, address,
|
||||||
|
sizeof ( miniroute->address ) );
|
||||||
|
miniroute->flags |= IPV6_HAS_ADDRESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( miniroute->prefix_len == IPV6_MAX_PREFIX_LEN )
|
||||||
|
miniroute->flags |= IPV6_HAS_ADDRESS;
|
||||||
|
|
||||||
|
/* Update scope */
|
||||||
|
miniroute->scope = ipv6_scope ( &miniroute->address );
|
||||||
|
|
||||||
|
/* Set or update router, if applicable */
|
||||||
if ( router ) {
|
if ( router ) {
|
||||||
changed = ( ( ! ( miniroute->flags & IPV6_HAS_ROUTER ) ) ||
|
|
||||||
( memcmp ( &miniroute->router, router,
|
|
||||||
sizeof ( miniroute->router ) ) != 0 ) );
|
|
||||||
miniroute->flags |= IPV6_HAS_ROUTER;
|
|
||||||
memcpy ( &miniroute->router, router,
|
memcpy ( &miniroute->router, router,
|
||||||
sizeof ( miniroute->router ) );
|
sizeof ( miniroute->router ) );
|
||||||
list_add_tail ( &miniroute->list, &ipv6_miniroutes );
|
miniroute->flags |= IPV6_HAS_ROUTER;
|
||||||
} else {
|
|
||||||
changed = ( miniroute->flags & IPV6_HAS_ROUTER );
|
|
||||||
miniroute->flags &= ~IPV6_HAS_ROUTER;
|
|
||||||
list_add ( &miniroute->list, &ipv6_miniroutes );
|
|
||||||
}
|
}
|
||||||
if ( changed )
|
|
||||||
ipv6_dump_miniroute ( miniroute );
|
|
||||||
|
|
||||||
|
ipv6_dump_miniroute ( miniroute );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add IPv6 on-link address
|
* Delete IPv6 minirouting table entry
|
||||||
*
|
*
|
||||||
* @v netdev Network device
|
* @v miniroute Routing table entry
|
||||||
* @v address IPv6 address
|
|
||||||
* @ret rc Return status code
|
|
||||||
*
|
|
||||||
* An on-link prefix for the address must already exist.
|
|
||||||
*/
|
*/
|
||||||
int ipv6_set_address ( struct net_device *netdev, struct in6_addr *address ) {
|
void ipv6_del_miniroute ( struct ipv6_miniroute *miniroute ) {
|
||||||
struct ipv6_miniroute *miniroute;
|
|
||||||
int changed;
|
|
||||||
|
|
||||||
/* Find routing table entry */
|
netdev_put ( miniroute->netdev );
|
||||||
miniroute = ipv6_miniroute ( netdev, address );
|
list_del ( &miniroute->list );
|
||||||
if ( ! miniroute )
|
free ( miniroute );
|
||||||
return -EADDRNOTAVAIL;
|
|
||||||
|
|
||||||
/* Record address */
|
|
||||||
changed = ( ( ! ( miniroute->flags & IPV6_HAS_ADDRESS ) ) ||
|
|
||||||
( memcmp ( &miniroute->address, address,
|
|
||||||
sizeof ( miniroute->address ) ) != 0 ) );
|
|
||||||
memcpy ( &miniroute->address, address, sizeof ( miniroute->address ) );
|
|
||||||
miniroute->flags |= IPV6_HAS_ADDRESS;
|
|
||||||
if ( changed )
|
|
||||||
ipv6_dump_miniroute ( miniroute );
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -275,9 +304,17 @@ int ipv6_set_address ( struct net_device *netdev, struct in6_addr *address ) {
|
|||||||
* @ret dest Next hop destination address
|
* @ret dest Next hop destination address
|
||||||
* @ret miniroute Routing table entry to use, or NULL if no route
|
* @ret miniroute Routing table entry to use, or NULL if no route
|
||||||
*/
|
*/
|
||||||
static struct ipv6_miniroute * ipv6_route ( unsigned int scope_id,
|
struct ipv6_miniroute * ipv6_route ( unsigned int scope_id,
|
||||||
struct in6_addr **dest ) {
|
struct in6_addr **dest ) {
|
||||||
struct ipv6_miniroute *miniroute;
|
struct ipv6_miniroute *miniroute;
|
||||||
|
struct ipv6_miniroute *chosen = NULL;
|
||||||
|
unsigned int best = 0;
|
||||||
|
unsigned int match_len;
|
||||||
|
unsigned int score;
|
||||||
|
unsigned int scope;
|
||||||
|
|
||||||
|
/* Calculate destination address scope */
|
||||||
|
scope = ipv6_scope ( *dest );
|
||||||
|
|
||||||
/* Find first usable route in routing table */
|
/* Find first usable route in routing table */
|
||||||
list_for_each_entry ( miniroute, &ipv6_miniroutes, list ) {
|
list_for_each_entry ( miniroute, &ipv6_miniroutes, list ) {
|
||||||
@ -286,35 +323,52 @@ static struct ipv6_miniroute * ipv6_route ( unsigned int scope_id,
|
|||||||
if ( ! netdev_is_open ( miniroute->netdev ) )
|
if ( ! netdev_is_open ( miniroute->netdev ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Skip routing table entries with no usable source address */
|
/* Skip entries with no usable source address */
|
||||||
if ( ! ( miniroute->flags & IPV6_HAS_ADDRESS ) )
|
if ( ! ( miniroute->flags & IPV6_HAS_ADDRESS ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( IN6_IS_ADDR_NONGLOBAL ( *dest ) ) {
|
/* Skip entries with a non-matching scope ID, if
|
||||||
|
* destination specifies a scope ID.
|
||||||
/* If destination is non-global, and the scope ID
|
|
||||||
* matches this network device, then use this route.
|
|
||||||
*/
|
*/
|
||||||
if ( miniroute->netdev->index == scope_id )
|
if ( scope_id && ( miniroute->netdev->index != scope_id ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Skip entries that are out of scope */
|
||||||
|
if ( miniroute->scope < scope )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Calculate match length */
|
||||||
|
match_len = ipv6_match_len ( miniroute, *dest );
|
||||||
|
|
||||||
|
/* If destination is on-link, then use this route */
|
||||||
|
if ( match_len >= miniroute->prefix_len )
|
||||||
return miniroute;
|
return miniroute;
|
||||||
|
|
||||||
} else {
|
/* If destination is unicast, then skip off-link
|
||||||
|
* entries with no router.
|
||||||
/* If destination is an on-link global
|
|
||||||
* address, then use this route.
|
|
||||||
*/
|
*/
|
||||||
if ( ipv6_is_on_link ( miniroute, *dest ) )
|
if ( ! ( IN6_IS_ADDR_MULTICAST ( *dest ) ||
|
||||||
return miniroute;
|
( miniroute->flags & IPV6_HAS_ROUTER ) ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
/* If destination is an off-link global
|
/* Choose best route, defined as being the route with
|
||||||
* address, and we have a default gateway,
|
* the smallest viable scope. If two routes both have
|
||||||
* then use this route.
|
* the same scope, then prefer the route with the
|
||||||
|
* longest match length.
|
||||||
*/
|
*/
|
||||||
if ( miniroute->flags & IPV6_HAS_ROUTER ) {
|
score = ( ( ( IPV6_SCOPE_MAX + 1 - miniroute->scope ) << 8 )
|
||||||
*dest = &miniroute->router;
|
+ match_len );
|
||||||
return miniroute;
|
if ( score > best ) {
|
||||||
|
chosen = miniroute;
|
||||||
|
best = score;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return chosen route, if any */
|
||||||
|
if ( chosen ) {
|
||||||
|
if ( ! IN6_IS_ADDR_MULTICAST ( *dest ) )
|
||||||
|
*dest = &chosen->router;
|
||||||
|
return chosen;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -902,7 +956,7 @@ static const char * ipv6_sock_ntoa ( struct sockaddr *sa ) {
|
|||||||
const char *netdev_name;
|
const char *netdev_name;
|
||||||
|
|
||||||
/* Identify network device, if applicable */
|
/* Identify network device, if applicable */
|
||||||
if ( IN6_IS_ADDR_NONGLOBAL ( in ) ) {
|
if ( IN6_IS_ADDR_LINKLOCAL ( in ) || IN6_IS_ADDR_MULTICAST ( in ) ) {
|
||||||
netdev = find_netdev_by_index ( sin6->sin6_scope_id );
|
netdev = find_netdev_by_index ( sin6->sin6_scope_id );
|
||||||
netdev_name = ( netdev ? netdev->name : "UNKNOWN" );
|
netdev_name = ( netdev ? netdev->name : "UNKNOWN" );
|
||||||
} else {
|
} else {
|
||||||
@ -968,7 +1022,8 @@ static int ipv6_sock_aton ( const char *string, struct sockaddr *sa ) {
|
|||||||
}
|
}
|
||||||
sin6->sin6_scope_id = netdev->index;
|
sin6->sin6_scope_id = netdev->index;
|
||||||
|
|
||||||
} else if ( IN6_IS_ADDR_NONGLOBAL ( &in ) ) {
|
} else if ( IN6_IS_ADDR_LINKLOCAL ( &in ) ||
|
||||||
|
IN6_IS_ADDR_MULTICAST ( &in ) ) {
|
||||||
|
|
||||||
/* If no network device is explicitly specified for a
|
/* If no network device is explicitly specified for a
|
||||||
* link-local or multicast address, default to using
|
* link-local or multicast address, default to using
|
||||||
@ -1061,61 +1116,235 @@ int format_ipv6_setting ( const struct setting_type *type __unused,
|
|||||||
return snprintf ( buf, len, "%s", inet6_ntoa ( ipv6 ) );
|
return snprintf ( buf, len, "%s", inet6_ntoa ( ipv6 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** IPv6 settings scope */
|
||||||
|
const struct settings_scope ipv6_settings_scope;
|
||||||
|
|
||||||
|
/** IPv6 address setting */
|
||||||
|
const struct setting ip6_setting __setting ( SETTING_IP6, ip6 ) = {
|
||||||
|
.name = "ip6",
|
||||||
|
.description = "IPv6 address",
|
||||||
|
.type = &setting_type_ipv6,
|
||||||
|
.scope = &ipv6_settings_scope,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** IPv6 prefix length setting */
|
||||||
|
const struct setting len6_setting __setting ( SETTING_IP6, len6 ) = {
|
||||||
|
.name = "len6",
|
||||||
|
.description = "IPv6 prefix length",
|
||||||
|
.type = &setting_type_int8,
|
||||||
|
.scope = &ipv6_settings_scope,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Default gateway setting */
|
||||||
|
const struct setting gateway6_setting __setting ( SETTING_IP6, gateway6 ) = {
|
||||||
|
.name = "gateway6",
|
||||||
|
.description = "IPv6 gateway",
|
||||||
|
.type = &setting_type_ipv6,
|
||||||
|
.scope = &ipv6_settings_scope,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create IPv6 network device
|
* Check applicability of IPv6 link-local address setting
|
||||||
*
|
*
|
||||||
* @v netdev Network device
|
* @v settings Settings block
|
||||||
* @ret rc Return status code
|
* @v setting Setting to fetch
|
||||||
|
* @ret applies Setting applies within this settings block
|
||||||
*/
|
*/
|
||||||
static int ipv6_probe ( struct net_device *netdev ) {
|
static int ipv6_applies ( struct settings *settings __unused,
|
||||||
struct ipv6_miniroute *miniroute;
|
const struct setting *setting ) {
|
||||||
struct in6_addr address;
|
|
||||||
|
return ( setting->scope == &ipv6_settings_scope );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch IPv6 link-local address setting
|
||||||
|
*
|
||||||
|
* @v settings Settings block
|
||||||
|
* @v setting Setting to fetch
|
||||||
|
* @v data Buffer to fill with setting data
|
||||||
|
* @v len Length of buffer
|
||||||
|
* @ret len Length of setting data, or negative error
|
||||||
|
*/
|
||||||
|
static int ipv6_fetch ( struct settings *settings, struct setting *setting,
|
||||||
|
void *data, size_t len ) {
|
||||||
|
struct net_device *netdev =
|
||||||
|
container_of ( settings->parent, struct net_device,
|
||||||
|
settings.settings );
|
||||||
|
struct in6_addr ip6;
|
||||||
|
uint8_t *len6;
|
||||||
int prefix_len;
|
int prefix_len;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Construct link-local address from EUI-64 as per RFC 2464 */
|
/* Construct link-local address from EUI-64 as per RFC 2464 */
|
||||||
memset ( &address, 0, sizeof ( address ) );
|
memset ( &ip6, 0, sizeof ( ip6 ) );
|
||||||
prefix_len = ipv6_link_local ( &address, netdev );
|
prefix_len = ipv6_link_local ( &ip6, netdev );
|
||||||
if ( prefix_len < 0 ) {
|
if ( prefix_len < 0 ) {
|
||||||
rc = prefix_len;
|
rc = prefix_len;
|
||||||
DBGC ( netdev, "IPv6 %s could not construct link-local "
|
|
||||||
"address: %s\n", netdev->name, strerror ( rc ) );
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create link-local address for this network device */
|
/* Handle setting */
|
||||||
miniroute = ipv6_add_miniroute ( netdev, &address, prefix_len,
|
if ( setting_cmp ( setting, &ip6_setting ) == 0 ) {
|
||||||
IPV6_HAS_ADDRESS );
|
|
||||||
if ( ! miniroute )
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
return 0;
|
/* Return link-local ip6 */
|
||||||
|
if ( len > sizeof ( ip6 ) )
|
||||||
|
len = sizeof ( ip6 );
|
||||||
|
memcpy ( data, &ip6, len );
|
||||||
|
return sizeof ( ip6 );
|
||||||
|
|
||||||
|
} else if ( setting_cmp ( setting, &len6_setting ) == 0 ) {
|
||||||
|
|
||||||
|
/* Return prefix length */
|
||||||
|
if ( len ) {
|
||||||
|
len6 = data;
|
||||||
|
*len6 = prefix_len;
|
||||||
}
|
}
|
||||||
|
return sizeof ( *len6 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** IPv6 link-local address settings operations */
|
||||||
|
static struct settings_operations ipv6_settings_operations = {
|
||||||
|
.applies = ipv6_applies,
|
||||||
|
.fetch = ipv6_fetch,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** IPv6 link-local address settings */
|
||||||
|
struct ipv6_settings {
|
||||||
|
/** Reference counter */
|
||||||
|
struct refcnt refcnt;
|
||||||
|
/** Settings interface */
|
||||||
|
struct settings settings;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy IPv6 network device
|
* Register IPv6 link-local address settings
|
||||||
*
|
*
|
||||||
* @v netdev Network device
|
* @v netdev Network device
|
||||||
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static void ipv6_remove ( struct net_device *netdev ) {
|
static int ipv6_register_settings ( struct net_device *netdev ) {
|
||||||
struct ipv6_miniroute *miniroute;
|
struct settings *parent = netdev_settings ( netdev );
|
||||||
struct ipv6_miniroute *tmp;
|
struct ipv6_settings *ipv6set;
|
||||||
|
int rc;
|
||||||
|
|
||||||
/* Delete all miniroutes for this network device */
|
/* Allocate and initialise structure */
|
||||||
list_for_each_entry_safe ( miniroute, tmp, &ipv6_miniroutes, list ) {
|
ipv6set = zalloc ( sizeof ( *ipv6set ) );
|
||||||
if ( miniroute->netdev == netdev ) {
|
if ( ! ipv6set ) {
|
||||||
netdev_put ( miniroute->netdev );
|
rc = -ENOMEM;
|
||||||
list_del ( &miniroute->list );
|
goto err_alloc;
|
||||||
free ( miniroute );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ref_init ( &ipv6set->refcnt, NULL );
|
||||||
|
settings_init ( &ipv6set->settings, &ipv6_settings_operations,
|
||||||
|
&ipv6set->refcnt, &ipv6_settings_scope );
|
||||||
|
ipv6set->settings.order = IPV6_ORDER_LINK_LOCAL;
|
||||||
|
|
||||||
|
/* Register settings */
|
||||||
|
if ( ( rc = register_settings ( &ipv6set->settings, parent,
|
||||||
|
IPV6_SETTINGS_NAME ) ) != 0 )
|
||||||
|
goto err_register;
|
||||||
|
|
||||||
|
err_register:
|
||||||
|
ref_put ( &ipv6set->refcnt );
|
||||||
|
err_alloc:
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** IPv6 network device driver */
|
/** IPv6 network device driver */
|
||||||
struct net_driver ipv6_driver __net_driver = {
|
struct net_driver ipv6_driver __net_driver = {
|
||||||
.name = "IPv6",
|
.name = "IPv6",
|
||||||
.probe = ipv6_probe,
|
.probe = ipv6_register_settings,
|
||||||
.remove = ipv6_remove,
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create IPv6 routing table based on configured settings
|
||||||
|
*
|
||||||
|
* @v netdev Network device
|
||||||
|
* @v settings Settings block
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
static int ipv6_create_routes ( struct net_device *netdev,
|
||||||
|
struct settings *settings ) {
|
||||||
|
struct settings *child;
|
||||||
|
struct settings *origin;
|
||||||
|
struct in6_addr ip6_buf;
|
||||||
|
struct in6_addr gateway6_buf;
|
||||||
|
struct in6_addr *ip6 = &ip6_buf;
|
||||||
|
struct in6_addr *gateway6 = &gateway6_buf;
|
||||||
|
uint8_t len6;
|
||||||
|
size_t len;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* First, create routing table for any child settings. We do
|
||||||
|
* this depth-first and in reverse order so that the end
|
||||||
|
* result reflects the relative priorities of the settings
|
||||||
|
* blocks.
|
||||||
|
*/
|
||||||
|
list_for_each_entry_reverse ( child, &settings->children, siblings )
|
||||||
|
ipv6_create_routes ( netdev, child );
|
||||||
|
|
||||||
|
/* Fetch IPv6 address, if any */
|
||||||
|
len = fetch_setting ( settings, &ip6_setting, &origin, NULL,
|
||||||
|
ip6, sizeof ( *ip6 ) );
|
||||||
|
if ( ( len != sizeof ( *ip6 ) ) || ( origin != settings ) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Fetch prefix length, if defined */
|
||||||
|
len = fetch_setting ( settings, &len6_setting, &origin, NULL,
|
||||||
|
&len6, sizeof ( len6 ) );
|
||||||
|
if ( ( len != sizeof ( len6 ) ) || ( origin != settings ) )
|
||||||
|
len6 = 0;
|
||||||
|
if ( len6 > IPV6_MAX_PREFIX_LEN )
|
||||||
|
len6 = IPV6_MAX_PREFIX_LEN;
|
||||||
|
|
||||||
|
/* Fetch gateway, if defined */
|
||||||
|
len = fetch_setting ( settings, &gateway6_setting, &origin, NULL,
|
||||||
|
gateway6, sizeof ( *gateway6 ) );
|
||||||
|
if ( ( len != sizeof ( *gateway6 ) ) || ( origin != settings ) )
|
||||||
|
gateway6 = NULL;
|
||||||
|
|
||||||
|
/* Create or update route */
|
||||||
|
if ( ( rc = ipv6_add_miniroute ( netdev, ip6, len6, gateway6 ) ) != 0){
|
||||||
|
DBGC ( netdev, "IPv6 %s could not add route: %s\n",
|
||||||
|
netdev->name, strerror ( rc ) );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create IPv6 routing table based on configured settings
|
||||||
|
*
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
static int ipv6_create_all_routes ( void ) {
|
||||||
|
struct ipv6_miniroute *miniroute;
|
||||||
|
struct ipv6_miniroute *tmp;
|
||||||
|
struct net_device *netdev;
|
||||||
|
struct settings *settings;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Delete all existing routes */
|
||||||
|
list_for_each_entry_safe ( miniroute, tmp, &ipv6_miniroutes, list )
|
||||||
|
ipv6_del_miniroute ( miniroute );
|
||||||
|
|
||||||
|
/* Create routes for each configured network device */
|
||||||
|
for_each_netdev ( netdev ) {
|
||||||
|
settings = netdev_settings ( netdev );
|
||||||
|
if ( ( rc = ipv6_create_routes ( netdev, settings ) ) != 0 )
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** IPv6 settings applicator */
|
||||||
|
struct settings_applicator ipv6_settings_applicator __settings_applicator = {
|
||||||
|
.apply = ipv6_create_all_routes,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Drag in objects via ipv6_protocol */
|
/* Drag in objects via ipv6_protocol */
|
||||||
|
413
third_party/ipxe/src/net/ndp.c
vendored
413
third_party/ipxe/src/net/ndp.c
vendored
@ -20,6 +20,7 @@
|
|||||||
FILE_LICENCE ( GPL2_OR_LATER );
|
FILE_LICENCE ( GPL2_OR_LATER );
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <byteswap.h>
|
#include <byteswap.h>
|
||||||
@ -41,6 +42,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
|||||||
static struct ipv6conf * ipv6conf_demux ( struct net_device *netdev );
|
static struct ipv6conf * ipv6conf_demux ( struct net_device *netdev );
|
||||||
static int
|
static int
|
||||||
ipv6conf_rx_router_advertisement ( struct net_device *netdev,
|
ipv6conf_rx_router_advertisement ( struct net_device *netdev,
|
||||||
|
struct in6_addr *router,
|
||||||
struct ndp_router_advertisement_header *radv,
|
struct ndp_router_advertisement_header *radv,
|
||||||
size_t len );
|
size_t len );
|
||||||
|
|
||||||
@ -340,11 +342,6 @@ ndp_rx_router_advertisement_prefix ( struct net_device *netdev,
|
|||||||
union ndp_option *option, size_t len ) {
|
union ndp_option *option, size_t len ) {
|
||||||
struct ndp_router_advertisement_header *radv = &ndp->radv;
|
struct ndp_router_advertisement_header *radv = &ndp->radv;
|
||||||
struct ndp_prefix_information_option *prefix_opt = &option->prefix;
|
struct ndp_prefix_information_option *prefix_opt = &option->prefix;
|
||||||
struct in6_addr *router = &sin6_src->sin6_addr;
|
|
||||||
struct in6_addr address;
|
|
||||||
struct ipv6conf *ipv6conf;
|
|
||||||
int prefix_len;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
if ( sizeof ( *prefix_opt ) > len ) {
|
if ( sizeof ( *prefix_opt ) > len ) {
|
||||||
@ -353,59 +350,13 @@ ndp_rx_router_advertisement_prefix ( struct net_device *netdev,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Identify IPv6 configurator, if any */
|
|
||||||
ipv6conf = ipv6conf_demux ( netdev );
|
|
||||||
DBGC ( netdev, "NDP %s found %sdefault router %s ",
|
DBGC ( netdev, "NDP %s found %sdefault router %s ",
|
||||||
netdev->name, ( radv->lifetime ? "" : "non-" ),
|
netdev->name, ( radv->lifetime ? "" : "non-" ),
|
||||||
inet6_ntoa ( &sin6_src->sin6_addr ) );
|
inet6_ntoa ( &sin6_src->sin6_addr ) );
|
||||||
DBGC ( netdev, "for %s-link %sautonomous prefix %s/%d%s\n",
|
DBGC ( netdev, "for %s-link %sautonomous prefix %s/%d\n",
|
||||||
( ( prefix_opt->flags & NDP_PREFIX_ON_LINK ) ? "on" : "off" ),
|
( ( prefix_opt->flags & NDP_PREFIX_ON_LINK ) ? "on" : "off" ),
|
||||||
( ( prefix_opt->flags & NDP_PREFIX_AUTONOMOUS ) ? "" : "non-" ),
|
( ( prefix_opt->flags & NDP_PREFIX_AUTONOMOUS ) ? "" : "non-" ),
|
||||||
inet6_ntoa ( &prefix_opt->prefix ),
|
inet6_ntoa ( &prefix_opt->prefix ), prefix_opt->prefix_len );
|
||||||
prefix_opt->prefix_len, ( ipv6conf ? "" : " (ignored)" ) );
|
|
||||||
|
|
||||||
/* Do nothing unless IPv6 autoconfiguration is in progress */
|
|
||||||
if ( ! ipv6conf )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Ignore off-link prefixes */
|
|
||||||
if ( ! ( prefix_opt->flags & NDP_PREFIX_ON_LINK ) )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Define prefix */
|
|
||||||
if ( ( rc = ipv6_set_prefix ( netdev, &prefix_opt->prefix,
|
|
||||||
prefix_opt->prefix_len,
|
|
||||||
( radv->lifetime ?
|
|
||||||
router : NULL ) ) ) != 0 ) {
|
|
||||||
DBGC ( netdev, "NDP %s could not define prefix %s/%d: %s\n",
|
|
||||||
netdev->name, inet6_ntoa ( &prefix_opt->prefix ),
|
|
||||||
prefix_opt->prefix_len, strerror ( rc ) );
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Perform stateless address autoconfiguration, if applicable */
|
|
||||||
if ( prefix_opt->flags & NDP_PREFIX_AUTONOMOUS ) {
|
|
||||||
memcpy ( &address, &prefix_opt->prefix, sizeof ( address ) );
|
|
||||||
prefix_len = ipv6_eui64 ( &address, netdev );
|
|
||||||
if ( prefix_len < 0 ) {
|
|
||||||
rc = prefix_len;
|
|
||||||
DBGC ( netdev, "NDP %s could not construct SLAAC "
|
|
||||||
"address: %s\n", netdev->name, strerror ( rc ) );
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
if ( prefix_len != prefix_opt->prefix_len ) {
|
|
||||||
DBGC ( netdev, "NDP %s incorrect SLAAC prefix length "
|
|
||||||
"%d (expected %d)\n", netdev->name,
|
|
||||||
prefix_opt->prefix_len, prefix_len );
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
if ( ( rc = ipv6_set_address ( netdev, &address ) ) != 0 ) {
|
|
||||||
DBGC ( netdev, "NDP %s could not set address %s: %s\n",
|
|
||||||
netdev->name, inet6_ntoa ( &address ),
|
|
||||||
strerror ( rc ) );
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -585,6 +536,7 @@ ndp_rx_router_advertisement ( struct io_buffer *iobuf,
|
|||||||
struct sockaddr_in6 *sin6_dest __unused ) {
|
struct sockaddr_in6 *sin6_dest __unused ) {
|
||||||
union ndp_header *ndp = iobuf->data;
|
union ndp_header *ndp = iobuf->data;
|
||||||
struct ndp_router_advertisement_header *radv = &ndp->radv;
|
struct ndp_router_advertisement_header *radv = &ndp->radv;
|
||||||
|
struct in6_addr *router = &sin6_src->sin6_addr;
|
||||||
size_t len = iob_len ( iobuf );
|
size_t len = iob_len ( iobuf );
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@ -595,8 +547,8 @@ ndp_rx_router_advertisement ( struct io_buffer *iobuf,
|
|||||||
goto err_options;
|
goto err_options;
|
||||||
|
|
||||||
/* Pass to IPv6 autoconfiguration */
|
/* Pass to IPv6 autoconfiguration */
|
||||||
if ( ( rc = ipv6conf_rx_router_advertisement ( netdev, radv,
|
if ( ( rc = ipv6conf_rx_router_advertisement ( netdev, router,
|
||||||
len ) ) != 0 )
|
radv, len ) ) != 0 )
|
||||||
goto err_ipv6conf;
|
goto err_ipv6conf;
|
||||||
|
|
||||||
err_ipv6conf:
|
err_ipv6conf:
|
||||||
@ -627,16 +579,30 @@ struct icmpv6_handler ndp_handlers[] __icmpv6_handler = {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** An NDP prefix settings block */
|
||||||
|
struct ndp_prefix_settings {
|
||||||
|
/** Settings interface */
|
||||||
|
struct settings settings;
|
||||||
|
/** Name */
|
||||||
|
char name[4];
|
||||||
|
/** Prefix information option */
|
||||||
|
struct ndp_prefix_information_option *prefix;
|
||||||
|
};
|
||||||
|
|
||||||
/** An NDP settings block */
|
/** An NDP settings block */
|
||||||
struct ndp_settings {
|
struct ndp_settings {
|
||||||
/** Reference counter */
|
/** Reference counter */
|
||||||
struct refcnt refcnt;
|
struct refcnt refcnt;
|
||||||
/** Settings interface */
|
/** Settings interface */
|
||||||
struct settings settings;
|
struct settings settings;
|
||||||
|
/** Router address */
|
||||||
|
struct in6_addr router;
|
||||||
|
/** Router lifetime */
|
||||||
|
unsigned int lifetime;
|
||||||
/** Length of NDP options */
|
/** Length of NDP options */
|
||||||
size_t len;
|
size_t len;
|
||||||
/** NDP options */
|
/** NDP options */
|
||||||
union ndp_option option[0];
|
union ndp_option options[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
/** NDP settings scope */
|
/** NDP settings scope */
|
||||||
@ -647,9 +613,11 @@ static const struct settings_scope ndp_settings_scope;
|
|||||||
*
|
*
|
||||||
* @v type NDP option type
|
* @v type NDP option type
|
||||||
* @v offset Starting offset of data
|
* @v offset Starting offset of data
|
||||||
|
* @v len Length of data (or 0 to use all remaining data)
|
||||||
* @ret tag NDP tag
|
* @ret tag NDP tag
|
||||||
*/
|
*/
|
||||||
#define NDP_TAG( type, offset ) ( ( (offset) << 8 ) | (type) )
|
#define NDP_TAG( type, offset, len ) \
|
||||||
|
( ( (len) << 16 ) | ( (offset) << 8 ) | (type) )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract NDP tag type
|
* Extract NDP tag type
|
||||||
@ -657,7 +625,7 @@ static const struct settings_scope ndp_settings_scope;
|
|||||||
* @v tag NDP tag
|
* @v tag NDP tag
|
||||||
* @ret type NDP option type
|
* @ret type NDP option type
|
||||||
*/
|
*/
|
||||||
#define NDP_TAG_TYPE( tag ) ( (tag) & 0xff )
|
#define NDP_TAG_TYPE( tag ) ( ( (tag) >> 0 ) & 0xff )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract NDP tag offset
|
* Extract NDP tag offset
|
||||||
@ -665,7 +633,23 @@ static const struct settings_scope ndp_settings_scope;
|
|||||||
* @v tag NDP tag
|
* @v tag NDP tag
|
||||||
* @ret offset Starting offset of data
|
* @ret offset Starting offset of data
|
||||||
*/
|
*/
|
||||||
#define NDP_TAG_OFFSET( tag ) ( (tag) >> 8 )
|
#define NDP_TAG_OFFSET( tag ) ( ( (tag) >> 8 ) & 0xff )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract NDP tag length
|
||||||
|
*
|
||||||
|
* @v tag NDP tag
|
||||||
|
* @ret len Length of data (or 0 to use all remaining data)
|
||||||
|
*/
|
||||||
|
#define NDP_TAG_LEN( tag ) ( ( (tag) >> 16 ) & 0xff )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract NDP tag instance
|
||||||
|
*
|
||||||
|
* @v tag NDP tag
|
||||||
|
* @ret instance Instance
|
||||||
|
*/
|
||||||
|
#define NDP_TAG_INSTANCE( tag ) ( ( (tag) >> 24 ) & 0xff )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check applicability of NDP setting
|
* Check applicability of NDP setting
|
||||||
@ -698,44 +682,58 @@ static int ndp_fetch ( struct settings *settings,
|
|||||||
container_of ( settings->parent, struct net_device,
|
container_of ( settings->parent, struct net_device,
|
||||||
settings.settings );
|
settings.settings );
|
||||||
union ndp_option *option;
|
union ndp_option *option;
|
||||||
unsigned int type = NDP_TAG_TYPE ( setting->tag );
|
unsigned int tag_type;
|
||||||
unsigned int offset = NDP_TAG_OFFSET ( setting->tag );
|
unsigned int tag_offset;
|
||||||
size_t remaining;
|
unsigned int tag_len;
|
||||||
|
unsigned int tag_instance;
|
||||||
|
size_t offset;
|
||||||
size_t option_len;
|
size_t option_len;
|
||||||
size_t payload_len;
|
void *option_data;
|
||||||
|
|
||||||
|
/* Parse setting tag */
|
||||||
|
tag_type = NDP_TAG_TYPE ( setting->tag );
|
||||||
|
tag_offset = NDP_TAG_OFFSET ( setting->tag );
|
||||||
|
tag_len = NDP_TAG_LEN ( setting->tag );
|
||||||
|
tag_instance = NDP_TAG_INSTANCE ( setting->tag );
|
||||||
|
|
||||||
/* Scan through NDP options for requested type. We can assume
|
/* Scan through NDP options for requested type. We can assume
|
||||||
* that the options are well-formed, otherwise they would have
|
* that the options are well-formed, otherwise they would have
|
||||||
* been rejected prior to being stored.
|
* been rejected prior to being stored.
|
||||||
*/
|
*/
|
||||||
option = ndpset->option;
|
for ( offset = 0 ; offset < ndpset->len ; offset += option_len ) {
|
||||||
remaining = ndpset->len;
|
|
||||||
while ( remaining ) {
|
|
||||||
|
|
||||||
/* Calculate option length */
|
/* Calculate option length */
|
||||||
|
option = ( ( ( void * ) ndpset->options ) + offset );
|
||||||
option_len = ( option->header.blocks * NDP_OPTION_BLKSZ );
|
option_len = ( option->header.blocks * NDP_OPTION_BLKSZ );
|
||||||
|
|
||||||
/* If this is the requested option, return it */
|
/* Skip options that do not match this tag */
|
||||||
if ( option->header.type == type ) {
|
if ( option->header.type != tag_type )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Skip previous instances of this option */
|
||||||
|
if ( tag_instance-- != 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
if ( offset > option_len ) {
|
if ( ( tag_offset + tag_len ) > option_len ) {
|
||||||
DBGC ( netdev, "NDP %s option %d too short\n",
|
DBGC ( netdev, "NDP %s option %d too short\n",
|
||||||
netdev->name, type );
|
netdev->name, tag_type );
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
payload_len = ( option_len - offset );
|
if ( ! tag_len )
|
||||||
|
tag_len = ( option_len - tag_offset );
|
||||||
|
option_data = ( ( ( void * ) option ) + tag_offset );
|
||||||
|
|
||||||
/* Copy data to output buffer */
|
/* Copy data to output buffer */
|
||||||
if ( len > payload_len )
|
if ( len > tag_len )
|
||||||
len = payload_len;
|
len = tag_len;
|
||||||
memcpy ( data, ( ( ( void * ) option ) + offset ), len);
|
memcpy ( data, option_data, len );
|
||||||
return payload_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Move to next option */
|
/* Default to hex if no type is specified */
|
||||||
option = ( ( ( void * ) option ) + option_len );
|
if ( ! setting->type )
|
||||||
remaining -= option_len;
|
setting->type = &setting_type_hex;
|
||||||
|
|
||||||
|
return tag_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
@ -747,22 +745,218 @@ static struct settings_operations ndp_settings_operations = {
|
|||||||
.fetch = ndp_fetch,
|
.fetch = ndp_fetch,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check applicability of NDP per-prefix setting
|
||||||
|
*
|
||||||
|
* @v settings Settings block
|
||||||
|
* @v setting Setting to fetch
|
||||||
|
* @ret applies Setting applies within this settings block
|
||||||
|
*/
|
||||||
|
static int ndp_prefix_applies ( struct settings *settings __unused,
|
||||||
|
const struct setting *setting ) {
|
||||||
|
|
||||||
|
return ( setting->scope == &ipv6_settings_scope );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch value of NDP IPv6 address setting
|
||||||
|
*
|
||||||
|
* @v settings Settings block
|
||||||
|
* @v data Buffer to fill with setting data
|
||||||
|
* @v len Length of buffer
|
||||||
|
* @ret len Length of setting data, or negative error
|
||||||
|
*/
|
||||||
|
static int ndp_prefix_fetch_ip6 ( struct settings *settings, void *data,
|
||||||
|
size_t len ) {
|
||||||
|
struct ndp_prefix_settings *prefset =
|
||||||
|
container_of ( settings, struct ndp_prefix_settings, settings );
|
||||||
|
struct ndp_settings *ndpset =
|
||||||
|
container_of ( settings->parent, struct ndp_settings, settings);
|
||||||
|
struct net_device *netdev =
|
||||||
|
container_of ( ndpset->settings.parent, struct net_device,
|
||||||
|
settings.settings );
|
||||||
|
struct ndp_prefix_information_option *prefix = prefset->prefix;
|
||||||
|
struct in6_addr ip6;
|
||||||
|
int prefix_len;
|
||||||
|
|
||||||
|
/* Skip dead prefixes */
|
||||||
|
if ( ! prefix->valid )
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
/* Construct IPv6 address via SLAAC, if applicable */
|
||||||
|
memcpy ( &ip6, &prefix->prefix, sizeof ( ip6 ) );
|
||||||
|
if ( prefix->flags & NDP_PREFIX_AUTONOMOUS ) {
|
||||||
|
prefix_len = ipv6_eui64 ( &ip6, netdev );
|
||||||
|
if ( prefix_len < 0 )
|
||||||
|
return prefix_len;
|
||||||
|
if ( prefix_len != prefix->prefix_len )
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill in IPv6 address */
|
||||||
|
if ( len > sizeof ( ip6 ) )
|
||||||
|
len = sizeof ( ip6 );
|
||||||
|
memcpy ( data, &ip6, len );
|
||||||
|
|
||||||
|
return sizeof ( ip6 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch value of NDP prefix length setting
|
||||||
|
*
|
||||||
|
* @v settings Settings block
|
||||||
|
* @v data Buffer to fill with setting data
|
||||||
|
* @v len Length of buffer
|
||||||
|
* @ret len Length of setting data, or negative error
|
||||||
|
*/
|
||||||
|
static int ndp_prefix_fetch_len6 ( struct settings *settings, void *data,
|
||||||
|
size_t len ) {
|
||||||
|
struct ndp_prefix_settings *prefset =
|
||||||
|
container_of ( settings, struct ndp_prefix_settings, settings );
|
||||||
|
struct ndp_prefix_information_option *prefix = prefset->prefix;
|
||||||
|
uint8_t *len6;
|
||||||
|
|
||||||
|
/* Fill in prefix length */
|
||||||
|
if ( len >= sizeof ( *len6 ) ) {
|
||||||
|
/* We treat an off-link prefix as having a prefix
|
||||||
|
* length covering the entire IPv6 address.
|
||||||
|
*/
|
||||||
|
len6 = data;
|
||||||
|
*len6 = ( ( prefix->flags & NDP_PREFIX_ON_LINK ) ?
|
||||||
|
prefix->prefix_len : -1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
return sizeof ( *len6 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch value of NDP router address setting
|
||||||
|
*
|
||||||
|
* @v settings Settings block
|
||||||
|
* @v data Buffer to fill with setting data
|
||||||
|
* @v len Length of buffer
|
||||||
|
* @ret len Length of setting data, or negative error
|
||||||
|
*/
|
||||||
|
static int ndp_prefix_fetch_gateway6 ( struct settings *settings,
|
||||||
|
void *data, size_t len ) {
|
||||||
|
struct ndp_settings *ndpset =
|
||||||
|
container_of ( settings->parent, struct ndp_settings, settings);
|
||||||
|
|
||||||
|
/* Treat non-routing router as non-existent */
|
||||||
|
if ( ! ndpset->lifetime )
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
/* Fill in router address */
|
||||||
|
if ( len > sizeof ( ndpset->router ) )
|
||||||
|
len = sizeof ( ndpset->router );
|
||||||
|
memcpy ( data, &ndpset->router, len );
|
||||||
|
|
||||||
|
return sizeof ( ndpset->router );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An NDP per-prefix setting operation */
|
||||||
|
struct ndp_prefix_operation {
|
||||||
|
/** Generic setting */
|
||||||
|
const struct setting *setting;
|
||||||
|
/**
|
||||||
|
* Fetch value of setting
|
||||||
|
*
|
||||||
|
* @v settings Settings block
|
||||||
|
* @v data Buffer to fill with setting data
|
||||||
|
* @v len Length of buffer
|
||||||
|
* @ret len Length of setting data, or negative error
|
||||||
|
*/
|
||||||
|
int ( * fetch ) ( struct settings *settings, void *data, size_t len );
|
||||||
|
};
|
||||||
|
|
||||||
|
/** NDP per-prefix settings operations */
|
||||||
|
static struct ndp_prefix_operation ndp_prefix_operations[] = {
|
||||||
|
{ &ip6_setting, ndp_prefix_fetch_ip6 },
|
||||||
|
{ &len6_setting, ndp_prefix_fetch_len6 },
|
||||||
|
{ &gateway6_setting, ndp_prefix_fetch_gateway6 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch value of NDP pre-prefix setting
|
||||||
|
*
|
||||||
|
* @v settings Settings block
|
||||||
|
* @v setting Setting to fetch
|
||||||
|
* @v data Buffer to fill with setting data
|
||||||
|
* @v len Length of buffer
|
||||||
|
* @ret len Length of setting data, or negative error
|
||||||
|
*/
|
||||||
|
static int ndp_prefix_fetch ( struct settings *settings,
|
||||||
|
struct setting *setting,
|
||||||
|
void *data, size_t len ) {
|
||||||
|
struct ndp_prefix_operation *op;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
/* Handle per-prefix settings */
|
||||||
|
for ( i = 0 ; i < ( sizeof ( ndp_prefix_operations ) /
|
||||||
|
sizeof ( ndp_prefix_operations[0] ) ) ; i++ ) {
|
||||||
|
op = &ndp_prefix_operations[i];
|
||||||
|
if ( setting_cmp ( setting, op->setting ) == 0 )
|
||||||
|
return op->fetch ( settings, data, len );
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** NDP per-prefix settings operations */
|
||||||
|
static struct settings_operations ndp_prefix_settings_operations = {
|
||||||
|
.applies = ndp_prefix_applies,
|
||||||
|
.fetch = ndp_prefix_fetch,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register NDP settings
|
* Register NDP settings
|
||||||
*
|
*
|
||||||
* @v netdev Network device
|
* @v netdev Network device
|
||||||
* @v option NDP options
|
* @v router Router address
|
||||||
|
* @v lifetime Router lifetime
|
||||||
|
* @v options NDP options
|
||||||
* @v len Length of options
|
* @v len Length of options
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int ndp_register_settings ( struct net_device *netdev,
|
static int ndp_register_settings ( struct net_device *netdev,
|
||||||
union ndp_option *option, size_t len ) {
|
struct in6_addr *router,
|
||||||
|
unsigned int lifetime,
|
||||||
|
union ndp_option *options, size_t len ) {
|
||||||
struct settings *parent = netdev_settings ( netdev );
|
struct settings *parent = netdev_settings ( netdev );
|
||||||
|
union ndp_option *option;
|
||||||
struct ndp_settings *ndpset;
|
struct ndp_settings *ndpset;
|
||||||
|
struct ndp_prefix_settings *prefset;
|
||||||
|
size_t offset;
|
||||||
|
size_t option_len;
|
||||||
|
unsigned int prefixes;
|
||||||
|
unsigned int instance;
|
||||||
|
int order;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
/* Count number of prefix options. We can assume that the
|
||||||
|
* options are well-formed, otherwise they would have been
|
||||||
|
* rejected prior to being stored.
|
||||||
|
*/
|
||||||
|
order = IPV6_ORDER_PREFIX_ONLY;
|
||||||
|
for ( prefixes = 0, offset = 0 ; offset < len ; offset += option_len ) {
|
||||||
|
|
||||||
|
/* Skip non-prefix options */
|
||||||
|
option = ( ( ( void * ) options ) + offset );
|
||||||
|
option_len = ( option->header.blocks * NDP_OPTION_BLKSZ );
|
||||||
|
if ( option->header.type != NDP_OPT_PREFIX )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Count number of prefixes */
|
||||||
|
prefixes++;
|
||||||
|
|
||||||
|
/* Increase overall order if we have SLAAC addresses */
|
||||||
|
if ( option->prefix.flags & NDP_PREFIX_AUTONOMOUS )
|
||||||
|
order = IPV6_ORDER_SLAAC;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate and initialise structure */
|
/* Allocate and initialise structure */
|
||||||
ndpset = zalloc ( sizeof ( *ndpset ) + len );
|
ndpset = zalloc ( sizeof ( *ndpset ) + len +
|
||||||
|
( prefixes * sizeof ( *prefset ) ) );
|
||||||
if ( ! ndpset ) {
|
if ( ! ndpset ) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto err_alloc;
|
goto err_alloc;
|
||||||
@ -770,14 +964,54 @@ static int ndp_register_settings ( struct net_device *netdev,
|
|||||||
ref_init ( &ndpset->refcnt, NULL );
|
ref_init ( &ndpset->refcnt, NULL );
|
||||||
settings_init ( &ndpset->settings, &ndp_settings_operations,
|
settings_init ( &ndpset->settings, &ndp_settings_operations,
|
||||||
&ndpset->refcnt, &ndp_settings_scope );
|
&ndpset->refcnt, &ndp_settings_scope );
|
||||||
|
ndpset->settings.order = order;
|
||||||
|
memcpy ( &ndpset->router, router, sizeof ( ndpset->router ) );
|
||||||
|
ndpset->lifetime = lifetime;
|
||||||
ndpset->len = len;
|
ndpset->len = len;
|
||||||
memcpy ( ndpset->option, option, len );
|
memcpy ( ndpset->options, options, len );
|
||||||
|
prefset = ( ( ( void * ) ndpset->options ) + len );
|
||||||
|
|
||||||
/* Register settings */
|
/* Register settings */
|
||||||
if ( ( rc = register_settings ( &ndpset->settings, parent,
|
if ( ( rc = register_settings ( &ndpset->settings, parent,
|
||||||
NDP_SETTINGS_NAME ) ) != 0 )
|
NDP_SETTINGS_NAME ) ) != 0 )
|
||||||
goto err_register;
|
goto err_register;
|
||||||
|
|
||||||
|
/* Construct and register per-prefix settings */
|
||||||
|
for ( instance = 0, offset = 0 ; offset < len ; offset += option_len ) {
|
||||||
|
|
||||||
|
/* Skip non-prefix options */
|
||||||
|
option = ( ( ( void * ) ndpset->options ) + offset );
|
||||||
|
option_len = ( option->header.blocks * NDP_OPTION_BLKSZ );
|
||||||
|
if ( option->header.type != NDP_OPT_PREFIX )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Initialise structure */
|
||||||
|
settings_init ( &prefset->settings,
|
||||||
|
&ndp_prefix_settings_operations,
|
||||||
|
&ndpset->refcnt, &ndp_settings_scope );
|
||||||
|
prefset->settings.order =
|
||||||
|
( ( option->prefix.flags & NDP_PREFIX_AUTONOMOUS ) ?
|
||||||
|
IPV6_ORDER_SLAAC : IPV6_ORDER_PREFIX_ONLY );
|
||||||
|
prefset->prefix = &option->prefix;
|
||||||
|
snprintf ( prefset->name, sizeof ( prefset->name ), "%d",
|
||||||
|
instance++ );
|
||||||
|
|
||||||
|
/* Register settings */
|
||||||
|
if ( ( rc = register_settings ( &prefset->settings,
|
||||||
|
&ndpset->settings,
|
||||||
|
prefset->name ) ) != 0 )
|
||||||
|
goto err_register_prefix;
|
||||||
|
|
||||||
|
/* Move to next per-prefix settings */
|
||||||
|
prefset++;
|
||||||
|
}
|
||||||
|
assert ( instance == prefixes );
|
||||||
|
|
||||||
|
ref_put ( &ndpset->refcnt );
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_register_prefix:
|
||||||
|
unregister_settings ( &ndpset->settings );
|
||||||
err_register:
|
err_register:
|
||||||
ref_put ( &ndpset->refcnt );
|
ref_put ( &ndpset->refcnt );
|
||||||
err_alloc:
|
err_alloc:
|
||||||
@ -785,11 +1019,11 @@ static int ndp_register_settings ( struct net_device *netdev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** DNS server setting */
|
/** DNS server setting */
|
||||||
const struct setting ndp_dns6_setting __setting ( SETTING_IP_EXTRA, dns6 ) = {
|
const struct setting ndp_dns6_setting __setting ( SETTING_IP6_EXTRA, dns6 ) = {
|
||||||
.name = "dns6",
|
.name = "dns6",
|
||||||
.description = "DNS server",
|
.description = "DNS server",
|
||||||
.tag = NDP_TAG ( NDP_OPT_RDNSS,
|
.tag = NDP_TAG ( NDP_OPT_RDNSS,
|
||||||
offsetof ( struct ndp_rdnss_option, addresses ) ),
|
offsetof ( struct ndp_rdnss_option, addresses ), 0 ),
|
||||||
.type = &setting_type_ipv6,
|
.type = &setting_type_ipv6,
|
||||||
.scope = &ndp_settings_scope,
|
.scope = &ndp_settings_scope,
|
||||||
};
|
};
|
||||||
@ -799,7 +1033,7 @@ const struct setting ndp_dnssl_setting __setting ( SETTING_IP_EXTRA, dnssl ) = {
|
|||||||
.name = "dnssl",
|
.name = "dnssl",
|
||||||
.description = "DNS search list",
|
.description = "DNS search list",
|
||||||
.tag = NDP_TAG ( NDP_OPT_DNSSL,
|
.tag = NDP_TAG ( NDP_OPT_DNSSL,
|
||||||
offsetof ( struct ndp_dnssl_option, names ) ),
|
offsetof ( struct ndp_dnssl_option, names ), 0 ),
|
||||||
.type = &setting_type_dnssl,
|
.type = &setting_type_dnssl,
|
||||||
.scope = &ndp_settings_scope,
|
.scope = &ndp_settings_scope,
|
||||||
};
|
};
|
||||||
@ -906,6 +1140,7 @@ static void ipv6conf_expired ( struct retry_timer *timer, int fail ) {
|
|||||||
* Handle router advertisement during IPv6 autoconfiguration
|
* Handle router advertisement during IPv6 autoconfiguration
|
||||||
*
|
*
|
||||||
* @v netdev Network device
|
* @v netdev Network device
|
||||||
|
* @v router Router address
|
||||||
* @v radv Router advertisement
|
* @v radv Router advertisement
|
||||||
* @v len Length of router advertisement
|
* @v len Length of router advertisement
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
@ -915,6 +1150,7 @@ static void ipv6conf_expired ( struct retry_timer *timer, int fail ) {
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ipv6conf_rx_router_advertisement ( struct net_device *netdev,
|
ipv6conf_rx_router_advertisement ( struct net_device *netdev,
|
||||||
|
struct in6_addr *router,
|
||||||
struct ndp_router_advertisement_header *radv,
|
struct ndp_router_advertisement_header *radv,
|
||||||
size_t len ) {
|
size_t len ) {
|
||||||
struct ipv6conf *ipv6conf;
|
struct ipv6conf *ipv6conf;
|
||||||
@ -938,8 +1174,9 @@ ipv6conf_rx_router_advertisement ( struct net_device *netdev,
|
|||||||
|
|
||||||
/* Register NDP settings */
|
/* Register NDP settings */
|
||||||
option_len = ( len - offsetof ( typeof ( *radv ), option ) );
|
option_len = ( len - offsetof ( typeof ( *radv ), option ) );
|
||||||
if ( ( rc = ndp_register_settings ( netdev, radv->option,
|
if ( ( rc = ndp_register_settings ( netdev, router,
|
||||||
option_len ) ) != 0 )
|
ntohl ( radv->lifetime ),
|
||||||
|
radv->option, option_len ) ) != 0 )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
/* Start DHCPv6 if required */
|
/* Start DHCPv6 if required */
|
||||||
|
79
third_party/ipxe/src/net/udp/dhcpv6.c
vendored
79
third_party/ipxe/src/net/udp/dhcpv6.c
vendored
@ -266,6 +266,8 @@ struct dhcpv6_settings {
|
|||||||
struct refcnt refcnt;
|
struct refcnt refcnt;
|
||||||
/** Settings block */
|
/** Settings block */
|
||||||
struct settings settings;
|
struct settings settings;
|
||||||
|
/** Leased address */
|
||||||
|
struct in6_addr lease;
|
||||||
/** Option list */
|
/** Option list */
|
||||||
struct dhcpv6_option_list options;
|
struct dhcpv6_option_list options;
|
||||||
};
|
};
|
||||||
@ -280,7 +282,32 @@ struct dhcpv6_settings {
|
|||||||
static int dhcpv6_applies ( struct settings *settings __unused,
|
static int dhcpv6_applies ( struct settings *settings __unused,
|
||||||
const struct setting *setting ) {
|
const struct setting *setting ) {
|
||||||
|
|
||||||
return ( setting->scope == &ipv6_scope );
|
return ( ( setting->scope == &dhcpv6_scope ) ||
|
||||||
|
( setting_cmp ( setting, &ip6_setting ) == 0 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch value of DHCPv6 leased address
|
||||||
|
*
|
||||||
|
* @v dhcpset DHCPv6 settings
|
||||||
|
* @v data Buffer to fill with setting data
|
||||||
|
* @v len Length of buffer
|
||||||
|
* @ret len Length of setting data, or negative error
|
||||||
|
*/
|
||||||
|
static int dhcpv6_fetch_lease ( struct dhcpv6_settings *dhcpv6set,
|
||||||
|
void *data, size_t len ) {
|
||||||
|
struct in6_addr *lease = &dhcpv6set->lease;
|
||||||
|
|
||||||
|
/* Do nothing unless a leased address exists */
|
||||||
|
if ( IN6_IS_ADDR_UNSPECIFIED ( lease ) )
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
/* Copy leased address */
|
||||||
|
if ( len > sizeof ( *lease ) )
|
||||||
|
len = sizeof ( *lease );
|
||||||
|
memcpy ( data, lease, len );
|
||||||
|
|
||||||
|
return sizeof ( *lease );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -300,6 +327,10 @@ static int dhcpv6_fetch ( struct settings *settings,
|
|||||||
const union dhcpv6_any_option *option;
|
const union dhcpv6_any_option *option;
|
||||||
size_t option_len;
|
size_t option_len;
|
||||||
|
|
||||||
|
/* Handle leased address */
|
||||||
|
if ( setting_cmp ( setting, &ip6_setting ) == 0 )
|
||||||
|
return dhcpv6_fetch_lease ( dhcpv6set, data, len );
|
||||||
|
|
||||||
/* Find option */
|
/* Find option */
|
||||||
option = dhcpv6_option ( &dhcpv6set->options, setting->tag );
|
option = dhcpv6_option ( &dhcpv6set->options, setting->tag );
|
||||||
if ( ! option )
|
if ( ! option )
|
||||||
@ -322,11 +353,13 @@ static struct settings_operations dhcpv6_settings_operations = {
|
|||||||
/**
|
/**
|
||||||
* Register DHCPv6 options as network device settings
|
* Register DHCPv6 options as network device settings
|
||||||
*
|
*
|
||||||
|
* @v lease DHCPv6 leased address
|
||||||
* @v options DHCPv6 option list
|
* @v options DHCPv6 option list
|
||||||
* @v parent Parent settings block
|
* @v parent Parent settings block
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int dhcpv6_register ( struct dhcpv6_option_list *options,
|
static int dhcpv6_register ( struct in6_addr *lease,
|
||||||
|
struct dhcpv6_option_list *options,
|
||||||
struct settings *parent ) {
|
struct settings *parent ) {
|
||||||
struct dhcpv6_settings *dhcpv6set;
|
struct dhcpv6_settings *dhcpv6set;
|
||||||
void *data;
|
void *data;
|
||||||
@ -341,12 +374,14 @@ static int dhcpv6_register ( struct dhcpv6_option_list *options,
|
|||||||
}
|
}
|
||||||
ref_init ( &dhcpv6set->refcnt, NULL );
|
ref_init ( &dhcpv6set->refcnt, NULL );
|
||||||
settings_init ( &dhcpv6set->settings, &dhcpv6_settings_operations,
|
settings_init ( &dhcpv6set->settings, &dhcpv6_settings_operations,
|
||||||
&dhcpv6set->refcnt, &ipv6_scope );
|
&dhcpv6set->refcnt, &dhcpv6_scope );
|
||||||
|
dhcpv6set->settings.order = IPV6_ORDER_DHCPV6;
|
||||||
data = ( ( ( void * ) dhcpv6set ) + sizeof ( *dhcpv6set ) );
|
data = ( ( ( void * ) dhcpv6set ) + sizeof ( *dhcpv6set ) );
|
||||||
len = options->len;
|
len = options->len;
|
||||||
memcpy ( data, options->data, len );
|
memcpy ( data, options->data, len );
|
||||||
dhcpv6set->options.data = data;
|
dhcpv6set->options.data = data;
|
||||||
dhcpv6set->options.len = len;
|
dhcpv6set->options.len = len;
|
||||||
|
memcpy ( &dhcpv6set->lease, lease, sizeof ( dhcpv6set->lease ) );
|
||||||
|
|
||||||
/* Register settings */
|
/* Register settings */
|
||||||
if ( ( rc = register_settings ( &dhcpv6set->settings, parent,
|
if ( ( rc = register_settings ( &dhcpv6set->settings, parent,
|
||||||
@ -427,8 +462,6 @@ enum dhcpv6_session_state_flags {
|
|||||||
DHCPV6_RX_RECORD_SERVER_ID = 0x04,
|
DHCPV6_RX_RECORD_SERVER_ID = 0x04,
|
||||||
/** Record received IPv6 address */
|
/** Record received IPv6 address */
|
||||||
DHCPV6_RX_RECORD_IAADDR = 0x08,
|
DHCPV6_RX_RECORD_IAADDR = 0x08,
|
||||||
/** Apply received IPv6 address */
|
|
||||||
DHCPV6_RX_APPLY_IAADDR = 0x10,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** DHCPv6 request state */
|
/** DHCPv6 request state */
|
||||||
@ -436,7 +469,7 @@ static struct dhcpv6_session_state dhcpv6_request = {
|
|||||||
.tx_type = DHCPV6_REQUEST,
|
.tx_type = DHCPV6_REQUEST,
|
||||||
.rx_type = DHCPV6_REPLY,
|
.rx_type = DHCPV6_REPLY,
|
||||||
.flags = ( DHCPV6_TX_IA_NA | DHCPV6_TX_IAADDR |
|
.flags = ( DHCPV6_TX_IA_NA | DHCPV6_TX_IAADDR |
|
||||||
DHCPV6_RX_RECORD_IAADDR | DHCPV6_RX_APPLY_IAADDR ),
|
DHCPV6_RX_RECORD_IAADDR ),
|
||||||
.next = NULL,
|
.next = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -835,40 +868,24 @@ static int dhcpv6_rx ( struct dhcpv6_session *dhcpv6,
|
|||||||
dhcpv6->server_duid_len );
|
dhcpv6->server_duid_len );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply identity association address, if applicable */
|
/* Transition to next state, if applicable */
|
||||||
if ( dhcpv6->state->flags & DHCPV6_RX_APPLY_IAADDR ) {
|
|
||||||
if ( ( rc = ipv6_set_address ( dhcpv6->netdev,
|
|
||||||
&dhcpv6->lease ) ) != 0 ) {
|
|
||||||
DBGC ( dhcpv6, "DHCPv6 %s could not apply %s: %s\n",
|
|
||||||
dhcpv6->netdev->name,
|
|
||||||
inet6_ntoa ( &dhcpv6->lease ), strerror ( rc ) );
|
|
||||||
/* This is plausibly the error we want to return */
|
|
||||||
dhcpv6->rc = rc;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Transition to next state or complete DHCPv6, as applicable */
|
|
||||||
if ( dhcpv6->state->next ) {
|
if ( dhcpv6->state->next ) {
|
||||||
|
|
||||||
/* Transition to next state */
|
|
||||||
dhcpv6_set_state ( dhcpv6, dhcpv6->state->next );
|
dhcpv6_set_state ( dhcpv6, dhcpv6->state->next );
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
goto done;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
/* Register settings */
|
/* Register settings */
|
||||||
if ( ( rc = dhcpv6_register ( &options, parent ) ) != 0 ) {
|
if ( ( rc = dhcpv6_register ( &dhcpv6->lease, &options,
|
||||||
DBGC ( dhcpv6, "DHCPv6 %s could not register "
|
parent ) ) != 0 ) {
|
||||||
"settings: %s\n", dhcpv6->netdev->name,
|
DBGC ( dhcpv6, "DHCPv6 %s could not register settings: %s\n",
|
||||||
strerror ( rc ) );
|
dhcpv6->netdev->name, strerror ( rc ) );
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark as complete */
|
/* Mark as complete */
|
||||||
dhcpv6_finished ( dhcpv6, 0 );
|
dhcpv6_finished ( dhcpv6, 0 );
|
||||||
DBGC ( dhcpv6, "DHCPv6 %s complete\n", dhcpv6->netdev->name );
|
DBGC ( dhcpv6, "DHCPv6 %s complete\n", dhcpv6->netdev->name );
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
free_iob ( iobuf );
|
free_iob ( iobuf );
|
||||||
@ -987,7 +1004,7 @@ const struct setting filename6_setting __setting ( SETTING_BOOT, filename ) = {
|
|||||||
.description = "Boot filename",
|
.description = "Boot filename",
|
||||||
.tag = DHCPV6_BOOTFILE_URL,
|
.tag = DHCPV6_BOOTFILE_URL,
|
||||||
.type = &setting_type_string,
|
.type = &setting_type_string,
|
||||||
.scope = &ipv6_scope,
|
.scope = &dhcpv6_scope,
|
||||||
};
|
};
|
||||||
|
|
||||||
/** DNS search list setting */
|
/** DNS search list setting */
|
||||||
@ -996,5 +1013,5 @@ const struct setting dnssl6_setting __setting ( SETTING_IP_EXTRA, dnssl ) = {
|
|||||||
.description = "DNS search list",
|
.description = "DNS search list",
|
||||||
.tag = DHCPV6_DOMAIN_LIST,
|
.tag = DHCPV6_DOMAIN_LIST,
|
||||||
.type = &setting_type_dnssl,
|
.type = &setting_type_dnssl,
|
||||||
.scope = &ipv6_scope,
|
.scope = &dhcpv6_scope,
|
||||||
};
|
};
|
||||||
|
6
third_party/ipxe/src/net/udp/dns.c
vendored
6
third_party/ipxe/src/net/udp/dns.c
vendored
@ -1048,7 +1048,7 @@ const struct setting_type setting_type_dnssl __setting_type = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** IPv4 DNS server setting */
|
/** IPv4 DNS server setting */
|
||||||
const struct setting dns_setting __setting ( SETTING_IP_EXTRA, dns ) = {
|
const struct setting dns_setting __setting ( SETTING_IP4_EXTRA, dns ) = {
|
||||||
.name = "dns",
|
.name = "dns",
|
||||||
.description = "DNS server",
|
.description = "DNS server",
|
||||||
.tag = DHCP_DNS_SERVERS,
|
.tag = DHCP_DNS_SERVERS,
|
||||||
@ -1056,12 +1056,12 @@ const struct setting dns_setting __setting ( SETTING_IP_EXTRA, dns ) = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** IPv6 DNS server setting */
|
/** IPv6 DNS server setting */
|
||||||
const struct setting dns6_setting __setting ( SETTING_IP_EXTRA, dns6 ) = {
|
const struct setting dns6_setting __setting ( SETTING_IP6_EXTRA, dns6 ) = {
|
||||||
.name = "dns6",
|
.name = "dns6",
|
||||||
.description = "DNS server",
|
.description = "DNS server",
|
||||||
.tag = DHCPV6_DNS_SERVERS,
|
.tag = DHCPV6_DNS_SERVERS,
|
||||||
.type = &setting_type_ipv6,
|
.type = &setting_type_ipv6,
|
||||||
.scope = &ipv6_scope,
|
.scope = &dhcpv6_scope,
|
||||||
};
|
};
|
||||||
|
|
||||||
/** DNS search list */
|
/** DNS search list */
|
||||||
|
2
third_party/ipxe/src/net/udp/syslog.c
vendored
2
third_party/ipxe/src/net/udp/syslog.c
vendored
@ -213,7 +213,7 @@ const struct setting syslog6_setting __setting ( SETTING_MISC, syslog6 ) = {
|
|||||||
.description = "Syslog server",
|
.description = "Syslog server",
|
||||||
.tag = DHCPV6_LOG_SERVERS,
|
.tag = DHCPV6_LOG_SERVERS,
|
||||||
.type = &setting_type_ipv6,
|
.type = &setting_type_ipv6,
|
||||||
.scope = &ipv6_scope,
|
.scope = &dhcpv6_scope,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
97
third_party/ipxe/src/tests/asn1_test.c
vendored
Normal file
97
third_party/ipxe/src/tests/asn1_test.c
vendored
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>.
|
||||||
|
*
|
||||||
|
* This program 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 2 of the
|
||||||
|
* License, or any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* You can also choose to distribute this program under the terms of
|
||||||
|
* the Unmodified Binary Distribution Licence (as given in the file
|
||||||
|
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* ASN.1 self-tests
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Forcibly enable assertions */
|
||||||
|
#undef NDEBUG
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ipxe/image.h>
|
||||||
|
#include <ipxe/asn1.h>
|
||||||
|
#include <ipxe/test.h>
|
||||||
|
#include "asn1_test.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report ASN.1 test result
|
||||||
|
*
|
||||||
|
* @v test ASN.1 test
|
||||||
|
* @v file Test code file
|
||||||
|
* @v line Test code line
|
||||||
|
*/
|
||||||
|
void asn1_okx ( struct asn1_test *test, const char *file, unsigned int line ) {
|
||||||
|
struct digest_algorithm *digest = &asn1_test_digest_algorithm;
|
||||||
|
struct asn1_cursor *cursor;
|
||||||
|
uint8_t ctx[digest->ctxsize];
|
||||||
|
uint8_t out[ASN1_TEST_DIGEST_SIZE];
|
||||||
|
unsigned int i;
|
||||||
|
size_t offset;
|
||||||
|
int next;
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
assert ( sizeof ( out ) == digest->digestsize );
|
||||||
|
|
||||||
|
/* Correct image data pointer */
|
||||||
|
test->image->data = virt_to_user ( ( void * ) test->image->data );
|
||||||
|
|
||||||
|
/* Check that image is detected as correct type */
|
||||||
|
okx ( register_image ( test->image ) == 0, file, line );
|
||||||
|
okx ( test->image->type == test->type, file, line );
|
||||||
|
|
||||||
|
/* Check that all ASN.1 objects can be extracted */
|
||||||
|
for ( offset = 0, i = 0 ; i < test->count ; offset = next, i++ ) {
|
||||||
|
|
||||||
|
/* Extract ASN.1 object */
|
||||||
|
next = image_asn1 ( test->image, offset, &cursor );
|
||||||
|
okx ( next >= 0, file, line );
|
||||||
|
okx ( ( ( size_t ) next ) > offset, file, line );
|
||||||
|
if ( next > 0 ) {
|
||||||
|
|
||||||
|
/* Calculate digest of ASN.1 object */
|
||||||
|
digest_init ( digest, ctx );
|
||||||
|
digest_update ( digest, ctx, cursor->data,
|
||||||
|
cursor->len );
|
||||||
|
digest_final ( digest, ctx, out );
|
||||||
|
|
||||||
|
/* Compare against expected digest */
|
||||||
|
okx ( memcmp ( out, test->expected[i].digest,
|
||||||
|
sizeof ( out ) ) == 0, file, line );
|
||||||
|
|
||||||
|
/* Free ASN.1 object */
|
||||||
|
free ( cursor );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that we have reached the end of the image */
|
||||||
|
okx ( offset == test->image->len, file, line );
|
||||||
|
|
||||||
|
/* Unregister image */
|
||||||
|
unregister_image ( test->image );
|
||||||
|
}
|
73
third_party/ipxe/src/tests/asn1_test.h
vendored
Normal file
73
third_party/ipxe/src/tests/asn1_test.h
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#ifndef _ASN1_TEST_H
|
||||||
|
#define _ASN1_TEST_H
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <ipxe/image.h>
|
||||||
|
#include <ipxe/sha1.h>
|
||||||
|
#include <ipxe/test.h>
|
||||||
|
|
||||||
|
/** Digest algorithm used for ASN.1 tests */
|
||||||
|
#define asn1_test_digest_algorithm sha1_algorithm
|
||||||
|
|
||||||
|
/** Digest size used for ASN.1 tests */
|
||||||
|
#define ASN1_TEST_DIGEST_SIZE SHA1_DIGEST_SIZE
|
||||||
|
|
||||||
|
/** An ASN.1 test digest */
|
||||||
|
struct asn1_test_digest {
|
||||||
|
/** Digest value */
|
||||||
|
uint8_t digest[ASN1_TEST_DIGEST_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
/** An ASN.1 test */
|
||||||
|
struct asn1_test {
|
||||||
|
/** Image type */
|
||||||
|
struct image_type *type;
|
||||||
|
/** Source image */
|
||||||
|
struct image *image;
|
||||||
|
/** Expected digests of ASN.1 objects */
|
||||||
|
struct asn1_test_digest *expected;
|
||||||
|
/** Number of ASN.1 objects */
|
||||||
|
unsigned int count;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define an ASN.1 test
|
||||||
|
*
|
||||||
|
* @v _name Test name
|
||||||
|
* @v _type Test image file type
|
||||||
|
* @v _file Test image file data
|
||||||
|
* @v ... Expected ASN.1 object digests
|
||||||
|
* @ret test ASN.1 test
|
||||||
|
*/
|
||||||
|
#define ASN1( _name, _type, _file, ... ) \
|
||||||
|
static const char _name ## __file[] = _file; \
|
||||||
|
static struct image _name ## __image = { \
|
||||||
|
.refcnt = REF_INIT ( ref_no_free ), \
|
||||||
|
.name = #_name, \
|
||||||
|
.data = ( userptr_t ) ( _name ## __file ), \
|
||||||
|
.len = sizeof ( _name ## __file ), \
|
||||||
|
}; \
|
||||||
|
static struct asn1_test_digest _name ## _expected[] = { \
|
||||||
|
__VA_ARGS__ \
|
||||||
|
}; \
|
||||||
|
static struct asn1_test _name = { \
|
||||||
|
.type = _type, \
|
||||||
|
.image = & _name ## __image, \
|
||||||
|
.expected = _name ## _expected, \
|
||||||
|
.count = ( sizeof ( _name ## _expected ) / \
|
||||||
|
sizeof ( _name ## _expected[0] ) ), \
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void asn1_okx ( struct asn1_test *test, const char *file,
|
||||||
|
unsigned int line );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report ASN.1 test result
|
||||||
|
*
|
||||||
|
* @v test ASN.1 test
|
||||||
|
*/
|
||||||
|
#define asn1_ok( test ) asn1_okx ( test, __FILE__, __LINE__ )
|
||||||
|
|
||||||
|
#endif /* _ASN1_TEST_H */
|
84
third_party/ipxe/src/tests/der_test.c
vendored
Normal file
84
third_party/ipxe/src/tests/der_test.c
vendored
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>.
|
||||||
|
*
|
||||||
|
* This program 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 2 of the
|
||||||
|
* License, or any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* You can also choose to distribute this program under the terms of
|
||||||
|
* the Unmodified Binary Distribution Licence (as given in the file
|
||||||
|
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* DER self-tests
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Forcibly enable assertions */
|
||||||
|
#undef NDEBUG
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ipxe/test.h>
|
||||||
|
#include <ipxe/der.h>
|
||||||
|
#include "asn1_test.h"
|
||||||
|
|
||||||
|
/** Define inline data */
|
||||||
|
#define DATA(...) { __VA_ARGS__ }
|
||||||
|
|
||||||
|
/** Define inline expected digest */
|
||||||
|
#define DIGEST(...) { { __VA_ARGS__ } }
|
||||||
|
|
||||||
|
/** 32-bit RSA private key */
|
||||||
|
ASN1 ( rsa32, &der_image_type,
|
||||||
|
DATA ( 0x30, 0x2c, 0x02, 0x01, 0x00, 0x02, 0x05, 0x00, 0xb7, 0x56,
|
||||||
|
0x5c, 0xb1, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x04, 0x66,
|
||||||
|
0xa4, 0xc4, 0x35, 0x02, 0x03, 0x00, 0xda, 0x9f, 0x02, 0x03,
|
||||||
|
0x00, 0xd6, 0xaf, 0x02, 0x02, 0x01, 0x59, 0x02, 0x02, 0x4e,
|
||||||
|
0xe1, 0x02, 0x03, 0x00, 0xa6, 0x5a ),
|
||||||
|
DIGEST ( 0x82, 0x66, 0x24, 0xd9, 0xc3, 0x98, 0x1e, 0x5e, 0x56, 0xed,
|
||||||
|
0xd0, 0xd0, 0x2a, 0x5e, 0x9c, 0x3a, 0x58, 0xdf, 0x76, 0x0d ) );
|
||||||
|
|
||||||
|
/** 64-bit RSA private key */
|
||||||
|
ASN1 ( rsa64, &der_image_type,
|
||||||
|
DATA ( 0x30, 0x3e, 0x02, 0x01, 0x00, 0x02, 0x09, 0x00, 0xa1, 0xba,
|
||||||
|
0xb5, 0x70, 0x00, 0x89, 0xc0, 0x43, 0x02, 0x03, 0x01, 0x00,
|
||||||
|
0x01, 0x02, 0x08, 0x43, 0x98, 0xc6, 0x3c, 0x5f, 0xdc, 0x98,
|
||||||
|
0x01, 0x02, 0x05, 0x00, 0xcf, 0x91, 0x1c, 0x5d, 0x02, 0x05,
|
||||||
|
0x00, 0xc7, 0x77, 0x85, 0x1f, 0x02, 0x05, 0x00, 0xbc, 0xb3,
|
||||||
|
0x33, 0x91, 0x02, 0x04, 0x1b, 0xf9, 0x38, 0x13, 0x02, 0x04,
|
||||||
|
0x19, 0xf2, 0x58, 0x86 ),
|
||||||
|
DIGEST ( 0xee, 0x17, 0x32, 0x31, 0xf0, 0x3d, 0xfd, 0xaa, 0x9b, 0x47,
|
||||||
|
0xaf, 0x7b, 0x4b, 0x52, 0x0b, 0xb1, 0xab, 0x25, 0x3f, 0x11 ) );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform DER self-test
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void der_test_exec ( void ) {
|
||||||
|
|
||||||
|
/* Perform tests */
|
||||||
|
asn1_ok ( &rsa32 );
|
||||||
|
asn1_ok ( &rsa64 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** DER self-test */
|
||||||
|
struct self_test der_test __self_test = {
|
||||||
|
.name = "der",
|
||||||
|
.exec = der_test_exec,
|
||||||
|
};
|
345
third_party/ipxe/src/tests/ipv6_test.c
vendored
345
third_party/ipxe/src/tests/ipv6_test.c
vendored
@ -41,6 +41,38 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
/** Define inline IPv6 address */
|
/** Define inline IPv6 address */
|
||||||
#define IPV6(...) { __VA_ARGS__ }
|
#define IPV6(...) { __VA_ARGS__ }
|
||||||
|
|
||||||
|
/** An IPv6 test routing table entry */
|
||||||
|
struct ipv6_test_route {
|
||||||
|
/** Local address */
|
||||||
|
const char *address;
|
||||||
|
/** Prefix length */
|
||||||
|
unsigned int prefix_len;
|
||||||
|
/** Router address (if any) */
|
||||||
|
const char *router;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** An IPv6 test routing table */
|
||||||
|
struct ipv6_test_table {
|
||||||
|
/** Test routing table entries */
|
||||||
|
const struct ipv6_test_route *routes;
|
||||||
|
/** Number of table entries */
|
||||||
|
unsigned int count;
|
||||||
|
/** Constructed routing table */
|
||||||
|
struct list_head list;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Define a test routing table */
|
||||||
|
#define TABLE( name, ... ) \
|
||||||
|
static const struct ipv6_test_route name ## _routes[] = { \
|
||||||
|
__VA_ARGS__ \
|
||||||
|
}; \
|
||||||
|
static struct ipv6_test_table name = { \
|
||||||
|
.routes = name ## _routes, \
|
||||||
|
.count = ( sizeof ( name ## _routes ) / \
|
||||||
|
sizeof ( name ## _routes[0] ) ), \
|
||||||
|
.list = LIST_HEAD_INIT ( name.list ), \
|
||||||
|
};
|
||||||
|
|
||||||
/** The unspecified IPv6 address */
|
/** The unspecified IPv6 address */
|
||||||
static const struct in6_addr sample_unspecified = {
|
static const struct in6_addr sample_unspecified = {
|
||||||
.s6_addr = IPV6 ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
.s6_addr = IPV6 ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
@ -53,6 +85,18 @@ static const struct in6_addr sample_link_local = {
|
|||||||
0x00, 0x00, 0x69, 0xff, 0xfe, 0x50, 0x58, 0x45 ),
|
0x00, 0x00, 0x69, 0xff, 0xfe, 0x50, 0x58, 0x45 ),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** A sample site-local IPv6 address */
|
||||||
|
static const struct in6_addr sample_site_local = {
|
||||||
|
.s6_addr = IPV6 ( 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 ),
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A sample ULA IPv6 address */
|
||||||
|
static const struct in6_addr sample_ula = {
|
||||||
|
.s6_addr = IPV6 ( 0xfd, 0x44, 0x91, 0x12, 0x64, 0x42, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x69, 0xff, 0xfe, 0x50, 0x58, 0x45 ),
|
||||||
|
};
|
||||||
|
|
||||||
/** A sample global IPv6 address */
|
/** A sample global IPv6 address */
|
||||||
static const struct in6_addr sample_global = {
|
static const struct in6_addr sample_global = {
|
||||||
.s6_addr = IPV6 ( 0x20, 0x01, 0x0b, 0xa8, 0x00, 0x00, 0x01, 0xd4,
|
.s6_addr = IPV6 ( 0x20, 0x01, 0x0b, 0xa8, 0x00, 0x00, 0x01, 0xd4,
|
||||||
@ -65,27 +109,57 @@ static const struct in6_addr sample_multicast = {
|
|||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ),
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Dummy network device used for routing tests */
|
||||||
|
static struct net_device ipv6_test_netdev = {
|
||||||
|
.refcnt = REF_INIT ( ref_no_free ),
|
||||||
|
.index = 42,
|
||||||
|
.state = NETDEV_OPEN,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Routing table with only a link-local address */
|
||||||
|
TABLE ( table_link_local,
|
||||||
|
{ "fe80::69ff:fe50:5845", 64, NULL } );
|
||||||
|
|
||||||
|
/** Routing table with a global address */
|
||||||
|
TABLE ( table_normal,
|
||||||
|
{ "fe80::69ff:fe50:5845", 64, NULL },
|
||||||
|
{ "2001:db8:3::1", 64, "fe80::1" } );
|
||||||
|
|
||||||
|
/** Routing table with multiple addresses and routers */
|
||||||
|
TABLE ( table_multi,
|
||||||
|
{ "fe80::69ff:fe50:5845", 64, NULL },
|
||||||
|
{ "2001:db8:3::1", 64, "fe80::1" },
|
||||||
|
{ "2001:db8:5::1", 64, NULL },
|
||||||
|
{ "2001:db8:42::1", 64, "fe80::2" },
|
||||||
|
{ "fd44:9112:6442::69ff:fe50:5845", 64, "fe80::1" },
|
||||||
|
{ "fd70:6ba9:50ae::69ff:fe50:5845", 64, "fe80::3" } );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Report an inet6_ntoa() test result
|
* Report an inet6_ntoa() test result
|
||||||
*
|
*
|
||||||
* @v addr IPv6 address
|
* @v addr IPv6 address
|
||||||
* @v text Expected textual representation
|
* @v text Expected textual representation
|
||||||
|
* @v file Test code file
|
||||||
|
* @v line Test code line
|
||||||
*/
|
*/
|
||||||
|
static void inet6_ntoa_okx ( const struct in6_addr *addr, const char *text,
|
||||||
|
const char *file, unsigned int line ) {
|
||||||
|
char *actual;
|
||||||
|
|
||||||
|
actual = inet6_ntoa ( addr );
|
||||||
|
DBG ( "inet6_ntoa ( %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ) "
|
||||||
|
"= %s\n", ntohs ( addr->s6_addr16[0] ),
|
||||||
|
ntohs ( addr->s6_addr16[1] ), ntohs ( addr->s6_addr16[2] ),
|
||||||
|
ntohs ( addr->s6_addr16[3] ), ntohs ( addr->s6_addr16[4] ),
|
||||||
|
ntohs ( addr->s6_addr16[5] ), ntohs ( addr->s6_addr16[6] ),
|
||||||
|
ntohs ( addr->s6_addr16[7] ), actual );
|
||||||
|
okx ( strcmp ( actual, text ) == 0, file, line );
|
||||||
|
}
|
||||||
#define inet6_ntoa_ok( addr, text ) do { \
|
#define inet6_ntoa_ok( addr, text ) do { \
|
||||||
static const struct in6_addr in = { \
|
static const struct in6_addr in = { \
|
||||||
.s6_addr = addr, \
|
.s6_addr = addr, \
|
||||||
}; \
|
}; \
|
||||||
static const char expected[] = text; \
|
inet6_ntoa_okx ( &in, text, __FILE__, __LINE__ ); \
|
||||||
char *actual; \
|
|
||||||
\
|
|
||||||
actual = inet6_ntoa ( &in ); \
|
|
||||||
DBG ( "inet6_ntoa ( %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ) " \
|
|
||||||
"= %s\n", ntohs ( in.s6_addr16[0] ), \
|
|
||||||
ntohs ( in.s6_addr16[1] ), ntohs ( in.s6_addr16[2] ), \
|
|
||||||
ntohs ( in.s6_addr16[3] ), ntohs ( in.s6_addr16[4] ), \
|
|
||||||
ntohs ( in.s6_addr16[5] ), ntohs ( in.s6_addr16[6] ), \
|
|
||||||
ntohs ( in.s6_addr16[7] ), actual ); \
|
|
||||||
ok ( strcmp ( actual, expected ) == 0 ); \
|
|
||||||
} while ( 0 )
|
} while ( 0 )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -93,31 +167,182 @@ static const struct in6_addr sample_multicast = {
|
|||||||
*
|
*
|
||||||
* @v text Textual representation
|
* @v text Textual representation
|
||||||
* @v addr Expected IPv6 address
|
* @v addr Expected IPv6 address
|
||||||
|
* @v file Test code file
|
||||||
|
* @v line Test code line
|
||||||
*/
|
*/
|
||||||
|
static void inet6_aton_okx ( const char *text, const struct in6_addr *addr,
|
||||||
|
const char *file, unsigned int line ) {
|
||||||
|
struct in6_addr actual;
|
||||||
|
|
||||||
|
okx ( inet6_aton ( text, &actual ) == 0, file, line );
|
||||||
|
DBG ( "inet6_aton ( \"%s\" ) = %s\n", text, inet6_ntoa ( &actual ) );
|
||||||
|
okx ( memcmp ( &actual, addr, sizeof ( actual ) ) == 0,
|
||||||
|
file, line );
|
||||||
|
}
|
||||||
#define inet6_aton_ok( text, addr ) do { \
|
#define inet6_aton_ok( text, addr ) do { \
|
||||||
static const char string[] = text; \
|
static const struct in6_addr in = { \
|
||||||
static const struct in6_addr expected = { \
|
|
||||||
.s6_addr = addr, \
|
.s6_addr = addr, \
|
||||||
}; \
|
}; \
|
||||||
struct in6_addr actual; \
|
inet6_aton_okx ( text, &in, __FILE__, __LINE__ ); \
|
||||||
\
|
|
||||||
ok ( inet6_aton ( string, &actual ) == 0 ); \
|
|
||||||
DBG ( "inet6_aton ( \"%s\" ) = %s\n", string, \
|
|
||||||
inet6_ntoa ( &actual ) ); \
|
|
||||||
ok ( memcmp ( &actual, &expected, sizeof ( actual ) ) == 0 ); \
|
|
||||||
} while ( 0 )
|
} while ( 0 )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Report an inet6_aton() failure test result
|
* Report an inet6_aton() failure test result
|
||||||
*
|
*
|
||||||
* @v text Textual representation
|
* @v text Textual representation
|
||||||
|
* @v file Test code file
|
||||||
|
* @v line Test code line
|
||||||
*/
|
*/
|
||||||
#define inet6_aton_fail_ok( text ) do { \
|
static void inet6_aton_fail_okx ( const char *text, const char *file,
|
||||||
static const char string[] = text; \
|
unsigned int line ) {
|
||||||
struct in6_addr dummy; \
|
struct in6_addr dummy;
|
||||||
\
|
|
||||||
ok ( inet6_aton ( string, &dummy ) != 0 ); \
|
okx ( inet6_aton ( text, &dummy ) != 0, file, line );
|
||||||
} while ( 0 )
|
}
|
||||||
|
#define inet6_aton_fail_ok( text ) \
|
||||||
|
inet6_aton_fail_okx ( text, __FILE__, __LINE__ )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create test routing table
|
||||||
|
*
|
||||||
|
* @v table Test routing table
|
||||||
|
* @v file Test code file
|
||||||
|
* @v line Test code line
|
||||||
|
*/
|
||||||
|
static void ipv6_table_okx ( struct ipv6_test_table *table, const char *file,
|
||||||
|
unsigned int line ) {
|
||||||
|
const struct ipv6_test_route *route;
|
||||||
|
struct in6_addr address;
|
||||||
|
struct in6_addr router;
|
||||||
|
struct list_head saved;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
okx ( list_empty ( &table->list ), file, line );
|
||||||
|
|
||||||
|
/* Save existing routing table */
|
||||||
|
INIT_LIST_HEAD ( &saved );
|
||||||
|
list_splice_init ( &ipv6_miniroutes, &saved );
|
||||||
|
|
||||||
|
/* Construct routing table */
|
||||||
|
for ( i = 0 ; i < table->count ; i++ ) {
|
||||||
|
|
||||||
|
/* Parse address and router (if applicable) */
|
||||||
|
route = &table->routes[i];
|
||||||
|
okx ( inet6_aton ( route->address, &address ) == 0,
|
||||||
|
file, line );
|
||||||
|
if ( route->router ) {
|
||||||
|
okx ( inet6_aton ( route->router, &router ) == 0,
|
||||||
|
file, line );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add routing table entry */
|
||||||
|
okx ( ipv6_add_miniroute ( &ipv6_test_netdev, &address,
|
||||||
|
route->prefix_len,
|
||||||
|
( route->router ?
|
||||||
|
&router : NULL ) ) == 0,
|
||||||
|
file, line );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save constructed routing table */
|
||||||
|
list_splice_init ( &ipv6_miniroutes, &table->list );
|
||||||
|
|
||||||
|
/* Restore original routing table */
|
||||||
|
list_splice ( &saved, &ipv6_miniroutes );
|
||||||
|
}
|
||||||
|
#define ipv6_table_ok( table ) \
|
||||||
|
ipv6_table_okx ( table, __FILE__, __LINE__ )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report an ipv6_route() test result
|
||||||
|
*
|
||||||
|
* @v table Test routing table
|
||||||
|
* @v dest Destination address
|
||||||
|
* @v src Expected source address, or NULL to expect failure
|
||||||
|
* @v next Expected next hop address, or NULL to expect destination
|
||||||
|
* @v file Test code file
|
||||||
|
* @v line Test code line
|
||||||
|
*/
|
||||||
|
static void ipv6_route_okx ( struct ipv6_test_table *table, const char *dest,
|
||||||
|
const char *src, const char *next,
|
||||||
|
const char *file, unsigned int line ) {
|
||||||
|
struct in6_addr in_dest;
|
||||||
|
struct in6_addr in_src;
|
||||||
|
struct in6_addr in_next;
|
||||||
|
struct in6_addr *actual;
|
||||||
|
struct ipv6_miniroute *miniroute;
|
||||||
|
struct list_head saved;
|
||||||
|
|
||||||
|
/* Switch to test routing table */
|
||||||
|
INIT_LIST_HEAD ( &saved );
|
||||||
|
list_splice_init ( &ipv6_miniroutes, &saved );
|
||||||
|
list_splice_init ( &table->list, &ipv6_miniroutes );
|
||||||
|
|
||||||
|
/* Parse addresses */
|
||||||
|
okx ( inet6_aton ( dest, &in_dest ) == 0, file, line );
|
||||||
|
if ( src )
|
||||||
|
okx ( inet6_aton ( src, &in_src ) == 0, file, line );
|
||||||
|
if ( next ) {
|
||||||
|
okx ( inet6_aton ( next, &in_next ) == 0, file, line );
|
||||||
|
} else {
|
||||||
|
memcpy ( &in_next, &in_dest, sizeof ( in_next ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform routing */
|
||||||
|
actual = &in_dest;
|
||||||
|
miniroute = ipv6_route ( ipv6_test_netdev.index, &actual );
|
||||||
|
|
||||||
|
/* Validate result */
|
||||||
|
if ( src ) {
|
||||||
|
|
||||||
|
/* Check that a route was found */
|
||||||
|
okx ( miniroute != NULL, file, line );
|
||||||
|
DBG ( "ipv6_route ( %s ) = %s", dest, inet6_ntoa ( actual ) );
|
||||||
|
DBG ( " from %s\n", inet6_ntoa ( &miniroute->address ) );
|
||||||
|
|
||||||
|
/* Check that expected source address was used */
|
||||||
|
okx ( memcmp ( &miniroute->address, &in_src,
|
||||||
|
sizeof ( in_src ) ) == 0, file, line );
|
||||||
|
|
||||||
|
/* Check that expected next hop address was used */
|
||||||
|
okx ( memcmp ( actual, &in_next, sizeof ( *actual ) ) == 0,
|
||||||
|
file, line );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Routing is expected to fail */
|
||||||
|
okx ( miniroute == NULL, file, line );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore original routing table */
|
||||||
|
list_splice_init ( &ipv6_miniroutes, &table->list );
|
||||||
|
list_splice ( &saved, &ipv6_miniroutes );
|
||||||
|
}
|
||||||
|
#define ipv6_route_ok( table, dest, src, next ) \
|
||||||
|
ipv6_route_okx ( table, dest, src, next, __FILE__, __LINE__ )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy test routing table
|
||||||
|
*
|
||||||
|
* @v table Test routing table
|
||||||
|
*/
|
||||||
|
static void ipv6_table_del ( struct ipv6_test_table *table ) {
|
||||||
|
struct ipv6_miniroute *miniroute;
|
||||||
|
struct ipv6_miniroute *tmp;
|
||||||
|
struct list_head saved;
|
||||||
|
|
||||||
|
/* Switch to test routing table */
|
||||||
|
INIT_LIST_HEAD ( &saved );
|
||||||
|
list_splice_init ( &ipv6_miniroutes, &saved );
|
||||||
|
list_splice_init ( &table->list, &ipv6_miniroutes );
|
||||||
|
|
||||||
|
/* Delete all existing routes */
|
||||||
|
list_for_each_entry_safe ( miniroute, tmp, &ipv6_miniroutes, list )
|
||||||
|
ipv6_del_miniroute ( miniroute );
|
||||||
|
|
||||||
|
/* Restore original routing table */
|
||||||
|
list_splice ( &saved, &ipv6_miniroutes );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform IPv6 self-tests
|
* Perform IPv6 self-tests
|
||||||
@ -128,16 +353,34 @@ static void ipv6_test_exec ( void ) {
|
|||||||
/* Address testing macros */
|
/* Address testing macros */
|
||||||
ok ( IN6_IS_ADDR_UNSPECIFIED ( &sample_unspecified ) );
|
ok ( IN6_IS_ADDR_UNSPECIFIED ( &sample_unspecified ) );
|
||||||
ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_link_local ) );
|
ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_link_local ) );
|
||||||
|
ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_site_local ) );
|
||||||
|
ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_ula ) );
|
||||||
ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_global ) );
|
ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_global ) );
|
||||||
ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_multicast ) );
|
ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_multicast ) );
|
||||||
ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_unspecified ) );
|
ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_unspecified ) );
|
||||||
ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_link_local ) );
|
ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_link_local ) );
|
||||||
|
ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_site_local ) );
|
||||||
|
ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_ula ) );
|
||||||
ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_global ) );
|
ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_global ) );
|
||||||
ok ( IN6_IS_ADDR_MULTICAST ( &sample_multicast ) );
|
ok ( IN6_IS_ADDR_MULTICAST ( &sample_multicast ) );
|
||||||
ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_unspecified ) );
|
ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_unspecified ) );
|
||||||
ok ( IN6_IS_ADDR_LINKLOCAL ( &sample_link_local ) );
|
ok ( IN6_IS_ADDR_LINKLOCAL ( &sample_link_local ) );
|
||||||
|
ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_site_local ) );
|
||||||
|
ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_ula ) );
|
||||||
ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_global ) );
|
ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_global ) );
|
||||||
ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_multicast ) );
|
ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_multicast ) );
|
||||||
|
ok ( ! IN6_IS_ADDR_SITELOCAL ( &sample_unspecified ) );
|
||||||
|
ok ( ! IN6_IS_ADDR_SITELOCAL ( &sample_link_local ) );
|
||||||
|
ok ( IN6_IS_ADDR_SITELOCAL ( &sample_site_local ) );
|
||||||
|
ok ( ! IN6_IS_ADDR_SITELOCAL ( &sample_ula ) );
|
||||||
|
ok ( ! IN6_IS_ADDR_SITELOCAL ( &sample_global ) );
|
||||||
|
ok ( ! IN6_IS_ADDR_SITELOCAL ( &sample_multicast ) );
|
||||||
|
ok ( ! IN6_IS_ADDR_ULA ( &sample_unspecified ) );
|
||||||
|
ok ( ! IN6_IS_ADDR_ULA ( &sample_link_local ) );
|
||||||
|
ok ( ! IN6_IS_ADDR_ULA ( &sample_site_local ) );
|
||||||
|
ok ( IN6_IS_ADDR_ULA ( &sample_ula ) );
|
||||||
|
ok ( ! IN6_IS_ADDR_ULA ( &sample_global ) );
|
||||||
|
ok ( ! IN6_IS_ADDR_ULA ( &sample_multicast ) );
|
||||||
|
|
||||||
/* inet6_ntoa() tests */
|
/* inet6_ntoa() tests */
|
||||||
inet6_ntoa_ok ( IPV6 ( 0x20, 0x01, 0x0b, 0xa8, 0x00, 0x00, 0x01, 0xd4,
|
inet6_ntoa_ok ( IPV6 ( 0x20, 0x01, 0x0b, 0xa8, 0x00, 0x00, 0x01, 0xd4,
|
||||||
@ -214,6 +457,58 @@ static void ipv6_test_exec ( void ) {
|
|||||||
inet6_aton_fail_ok ( "2001:db8::1::2" );
|
inet6_aton_fail_ok ( "2001:db8::1::2" );
|
||||||
inet6_aton_fail_ok ( "2001:ba8:0:1d4:::6950:5845" );
|
inet6_aton_fail_ok ( "2001:ba8:0:1d4:::6950:5845" );
|
||||||
inet6_aton_fail_ok ( ":::" );
|
inet6_aton_fail_ok ( ":::" );
|
||||||
|
|
||||||
|
/* Create test routing tables */
|
||||||
|
ipv6_table_ok ( &table_link_local );
|
||||||
|
ipv6_table_ok ( &table_normal );
|
||||||
|
ipv6_table_ok ( &table_multi );
|
||||||
|
|
||||||
|
/* Routing table with only a link-local address */
|
||||||
|
ipv6_route_ok ( &table_link_local, "fe80::1",
|
||||||
|
"fe80::69ff:fe50:5845", NULL );
|
||||||
|
ipv6_route_ok ( &table_link_local, "2001:db8:1::1",
|
||||||
|
NULL, NULL );
|
||||||
|
ipv6_route_ok ( &table_link_local, "ff02::1",
|
||||||
|
"fe80::69ff:fe50:5845", NULL );
|
||||||
|
|
||||||
|
/** Routing table with a global address */
|
||||||
|
ipv6_route_ok ( &table_normal, "fe80::1",
|
||||||
|
"fe80::69ff:fe50:5845", NULL );
|
||||||
|
ipv6_route_ok ( &table_normal, "2001:db8:3::42",
|
||||||
|
"2001:db8:3::1", NULL );
|
||||||
|
ipv6_route_ok ( &table_normal, "2001:ba8:0:1d4::6950:5845",
|
||||||
|
"2001:db8:3::1", "fe80::1" );
|
||||||
|
ipv6_route_ok ( &table_normal, "ff02::1",
|
||||||
|
"fe80::69ff:fe50:5845", NULL );
|
||||||
|
ipv6_route_ok ( &table_normal, "ff0e::1",
|
||||||
|
"2001:db8:3::1", NULL );
|
||||||
|
|
||||||
|
/** Routing table with multiple addresses and routers */
|
||||||
|
ipv6_route_ok ( &table_multi, "fe80::1",
|
||||||
|
"fe80::69ff:fe50:5845", NULL );
|
||||||
|
ipv6_route_ok ( &table_multi, "2001:db8:3::17",
|
||||||
|
"2001:db8:3::1", NULL );
|
||||||
|
ipv6_route_ok ( &table_multi, "2001:db8:5::92",
|
||||||
|
"2001:db8:5::1", NULL );
|
||||||
|
ipv6_route_ok ( &table_multi, "2001:db8:42::17",
|
||||||
|
"2001:db8:42::1", NULL );
|
||||||
|
ipv6_route_ok ( &table_multi, "2001:db8:5:1::17",
|
||||||
|
"2001:db8:3::1", "fe80::1" );
|
||||||
|
ipv6_route_ok ( &table_multi, "fd44:9112:6442::1",
|
||||||
|
"fd44:9112:6442::69ff:fe50:5845", NULL );
|
||||||
|
ipv6_route_ok ( &table_multi, "fd70:6ba9:50ae::1",
|
||||||
|
"fd70:6ba9:50ae::69ff:fe50:5845", NULL );
|
||||||
|
ipv6_route_ok ( &table_multi, "fd40::3",
|
||||||
|
"fd44:9112:6442::69ff:fe50:5845", "fe80::1" );
|
||||||
|
ipv6_route_ok ( &table_multi, "fd70::2",
|
||||||
|
"fd70:6ba9:50ae::69ff:fe50:5845", "fe80::3" );
|
||||||
|
ipv6_route_ok ( &table_multi, "ff02::1",
|
||||||
|
"fe80::69ff:fe50:5845", NULL );
|
||||||
|
|
||||||
|
/* Destroy test routing tables */
|
||||||
|
ipv6_table_del ( &table_link_local );
|
||||||
|
ipv6_table_del ( &table_normal );
|
||||||
|
ipv6_table_del ( &table_multi );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** IPv6 self-test */
|
/** IPv6 self-test */
|
||||||
|
107
third_party/ipxe/src/tests/pem_test.c
vendored
Normal file
107
third_party/ipxe/src/tests/pem_test.c
vendored
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>.
|
||||||
|
*
|
||||||
|
* This program 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 2 of the
|
||||||
|
* License, or any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* You can also choose to distribute this program under the terms of
|
||||||
|
* the Unmodified Binary Distribution Licence (as given in the file
|
||||||
|
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* PEM self-tests
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Forcibly enable assertions */
|
||||||
|
#undef NDEBUG
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ipxe/test.h>
|
||||||
|
#include <ipxe/pem.h>
|
||||||
|
#include "asn1_test.h"
|
||||||
|
|
||||||
|
/** Define inline expected digest */
|
||||||
|
#define DIGEST(...) { { __VA_ARGS__ } }
|
||||||
|
|
||||||
|
/** Single RSA private key */
|
||||||
|
ASN1 ( single, &pem_image_type,
|
||||||
|
"-----BEGIN RSA PRIVATE KEY-----\n"
|
||||||
|
"MCwCAQACBQC6loItAgMBAAECBCqhYIkCAwDyVwIDAMUbAgMAr9kCAmr9AgIaWQ==\n"
|
||||||
|
"-----END RSA PRIVATE KEY-----\n",
|
||||||
|
DIGEST ( 0xb9, 0x38, 0x83, 0xcd, 0xf4, 0x58, 0xa9, 0xa2, 0x84, 0x11,
|
||||||
|
0xfa, 0x0b, 0x6f, 0xdc, 0x3e, 0xa3, 0x7c, 0x90, 0x7c, 0x2d ) );
|
||||||
|
|
||||||
|
/** Three concatenated RSA private keys */
|
||||||
|
ASN1 ( multiple, &pem_image_type,
|
||||||
|
"-----BEGIN RSA PRIVATE KEY-----\n"
|
||||||
|
"MCwCAQACBQDtbjyVAgMBAAECBQCEOtJxAgMA+xsCAwDyDwICLGsCAgqTAgIxVQ==\n"
|
||||||
|
"-----END RSA PRIVATE KEY-----\n"
|
||||||
|
"-----BEGIN RSA PRIVATE KEY-----\n"
|
||||||
|
"MCwCAQACBQC3VlyxAgMBAAECBGakxDUCAwDanwIDANavAgIBWQICTuECAwCmWg==\n"
|
||||||
|
"-----END RSA PRIVATE KEY-----\n"
|
||||||
|
"-----BEGIN RSA PRIVATE KEY-----\n"
|
||||||
|
"MCwCAQACBQC89dS1AgMBAAECBQCxjnLBAgMA3qcCAwDZQwICP3cCAgpRAgI57A==\n"
|
||||||
|
"-----END RSA PRIVATE KEY-----\n",
|
||||||
|
DIGEST ( 0x9c, 0xb2, 0xc1, 0xa0, 0x9c, 0xcb, 0x11, 0xbf, 0x80, 0xd0,
|
||||||
|
0x8c, 0xe5, 0xda, 0xf2, 0x3b, 0x2c, 0xca, 0x64, 0x25, 0x8a ),
|
||||||
|
DIGEST ( 0x82, 0x66, 0x24, 0xd9, 0xc3, 0x98, 0x1e, 0x5e, 0x56, 0xed,
|
||||||
|
0xd0, 0xd0, 0x2a, 0x5e, 0x9c, 0x3a, 0x58, 0xdf, 0x76, 0x0d ),
|
||||||
|
DIGEST ( 0x01, 0xd2, 0x8a, 0x74, 0x42, 0x08, 0x0f, 0xb0, 0x03, 0x82,
|
||||||
|
0xcd, 0xa3, 0xdc, 0x78, 0xfe, 0xd7, 0xa3, 0x28, 0xfc, 0x29 ) );
|
||||||
|
|
||||||
|
/** Two RSA private keys with various bits of noise added */
|
||||||
|
ASN1 ( noisy, &pem_image_type,
|
||||||
|
"Hello world! This is uninteresting stuff before the actual data.\n"
|
||||||
|
"-----BEGIN RSA PRIVATE KEY-----\n"
|
||||||
|
"MCwCAQACBQC3VlyxAgMBAAECBGakxDUCAwDanwIDANavAgIBWQICTuECAwCmWg==\n"
|
||||||
|
"-----END RSA PRIVATE KEY-----\n"
|
||||||
|
"Here is some more uninteresting stuff.\n"
|
||||||
|
"Followed by what is actually another RSA private key, but with "
|
||||||
|
"extra whitespace added, and the description change to pretend "
|
||||||
|
"it's a certificate\n"
|
||||||
|
"-----BEGIN CERTIFICATE-----\n"
|
||||||
|
" MCwCAQACBQC6loItAgMBAAECBCqhYIkCAwD\r\n"
|
||||||
|
" yVwIDAMUbAgMAr9kCAmr9AgIaWQ== \r\n"
|
||||||
|
"-----END CERTIFICATE-----\n"
|
||||||
|
"and some trailing garbage as well\n"
|
||||||
|
"and more garbage with no final newline",
|
||||||
|
DIGEST ( 0x82, 0x66, 0x24, 0xd9, 0xc3, 0x98, 0x1e, 0x5e, 0x56, 0xed,
|
||||||
|
0xd0, 0xd0, 0x2a, 0x5e, 0x9c, 0x3a, 0x58, 0xdf, 0x76, 0x0d ),
|
||||||
|
DIGEST ( 0xb9, 0x38, 0x83, 0xcd, 0xf4, 0x58, 0xa9, 0xa2, 0x84, 0x11,
|
||||||
|
0xfa, 0x0b, 0x6f, 0xdc, 0x3e, 0xa3, 0x7c, 0x90, 0x7c, 0x2d ) );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform PEM self-test
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void pem_test_exec ( void ) {
|
||||||
|
|
||||||
|
/* Perform tests */
|
||||||
|
asn1_ok ( &single );
|
||||||
|
asn1_ok ( &multiple );
|
||||||
|
asn1_ok ( &noisy );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** PEM self-test */
|
||||||
|
struct self_test pem_test __self_test = {
|
||||||
|
.name = "pem",
|
||||||
|
.exec = pem_test_exec,
|
||||||
|
};
|
2
third_party/ipxe/src/tests/tests.c
vendored
2
third_party/ipxe/src/tests/tests.c
vendored
@ -69,3 +69,5 @@ REQUIRE_OBJECT ( pccrc_test );
|
|||||||
REQUIRE_OBJECT ( linebuf_test );
|
REQUIRE_OBJECT ( linebuf_test );
|
||||||
REQUIRE_OBJECT ( iobuf_test );
|
REQUIRE_OBJECT ( iobuf_test );
|
||||||
REQUIRE_OBJECT ( bitops_test );
|
REQUIRE_OBJECT ( bitops_test );
|
||||||
|
REQUIRE_OBJECT ( der_test );
|
||||||
|
REQUIRE_OBJECT ( pem_test );
|
||||||
|
22
third_party/ipxe/src/usr/imgtrust.c
vendored
22
third_party/ipxe/src/usr/imgtrust.c
vendored
@ -50,30 +50,28 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
*/
|
*/
|
||||||
int imgverify ( struct image *image, struct image *signature,
|
int imgverify ( struct image *image, struct image *signature,
|
||||||
const char *name ) {
|
const char *name ) {
|
||||||
size_t len;
|
struct asn1_cursor *data;
|
||||||
void *data;
|
|
||||||
struct cms_signature *sig;
|
struct cms_signature *sig;
|
||||||
struct cms_signer_info *info;
|
struct cms_signer_info *info;
|
||||||
time_t now;
|
time_t now;
|
||||||
|
int next;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Mark image as untrusted */
|
/* Mark image as untrusted */
|
||||||
image_untrust ( image );
|
image_untrust ( image );
|
||||||
|
|
||||||
/* Copy signature to internal memory */
|
/* Get raw signature data */
|
||||||
len = signature->len;
|
next = image_asn1 ( signature, 0, &data );
|
||||||
data = malloc ( len );
|
if ( next < 0 ) {
|
||||||
if ( ! data ) {
|
rc = next;
|
||||||
rc = -ENOMEM;
|
goto err_asn1;
|
||||||
goto err_alloc;
|
|
||||||
}
|
}
|
||||||
copy_from_user ( data, signature->data, 0, len );
|
|
||||||
|
|
||||||
/* Parse signature */
|
/* Parse signature */
|
||||||
if ( ( rc = cms_signature ( data, len, &sig ) ) != 0 )
|
if ( ( rc = cms_signature ( data->data, data->len, &sig ) ) != 0 )
|
||||||
goto err_parse;
|
goto err_parse;
|
||||||
|
|
||||||
/* Free internal copy of signature */
|
/* Free raw signature data */
|
||||||
free ( data );
|
free ( data );
|
||||||
data = NULL;
|
data = NULL;
|
||||||
|
|
||||||
@ -107,7 +105,7 @@ int imgverify ( struct image *image, struct image *signature,
|
|||||||
cms_put ( sig );
|
cms_put ( sig );
|
||||||
err_parse:
|
err_parse:
|
||||||
free ( data );
|
free ( data );
|
||||||
err_alloc:
|
err_asn1:
|
||||||
syslog ( LOG_ERR, "Image \"%s\" signature bad: %s\n",
|
syslog ( LOG_ERR, "Image \"%s\" signature bad: %s\n",
|
||||||
image->name, strerror ( rc ) );
|
image->name, strerror ( rc ) );
|
||||||
return rc;
|
return rc;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user