Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP2:GA
elilo
elilo-ipv6.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File elilo-ipv6.diff of Package elilo
--- fs/netfs.c | 257 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- glue_netfs.c | 53 ++++++++++-- strops.c | 11 ++ strops.h | 1 4 files changed, 302 insertions(+), 20 deletions(-) --- a/glue_netfs.c +++ b/glue_netfs.c @@ -133,6 +133,17 @@ netfs_set_default_path(netfs_interface_t return EFI_SUCCESS; } +static INTN +non_zero(UINT8 *c, UINTN len) +{ + int i; + for (i=0 ; i < len ; i++) { + if (c[i]) + return 1; + } + return 0; +} + static EFI_STATUS netfs_setdefaults(VOID *intf, config_file_t *config, CHAR16 *kname, UINTN maxlen, CHAR16 *devpath) { @@ -140,7 +151,7 @@ netfs_setdefaults(VOID *intf, config_fil netfs_info_t info; EFI_STATUS status; UINT8 *ipaddr; - UINTN m; + UINTN m, i; CHAR16 ip_var[64], str[64]; UINT8 *ip; @@ -165,6 +176,9 @@ netfs_setdefaults(VOID *intf, config_fil set_var(VAR_NETFS_HOSTNAME, info.hostname); set_var(VAR_NETFS_DOMAINAME, info.domainame); + DBG_PRT((L"netfs_setdefaults: hostname=%s (IPv%a)", info.hostname, + (info.using_ipv6 ? "6" : "4"))); + if (info.using_pxe) { DBG_PRT((L"netfs_setdefaults: using_pxe")); @@ -184,13 +198,10 @@ netfs_setdefaults(VOID *intf, config_fil # if defined(CONFIG_ia64) # define CONFIG_ARCH_EXTENSION L"-ia64.conf\0" -# define EXTENSION_LENGTH 11 # elif defined (CONFIG_ia32) # define CONFIG_ARCH_EXTENSION L"-ia32.conf\0" -# define EXTENSION_LENGTH 11 # elif defined (CONFIG_x86_64) # define CONFIG_ARCH_EXTENSION L"-x86_64.conf\0" -# define EXTENSION_LENGTH 13 # else # error "You need to specfy your default arch config file" # endif @@ -203,31 +214,57 @@ netfs_setdefaults(VOID *intf, config_fil * the filenames are constructed based on the IP(v4) address */ convert_ip2hex(ipaddr, m, str); +#if 1 + i = 0; + if (non_zero(ipaddr, m)) { + int nr = (m==16)? 10 : 6; + int st = (m==16)? 2 : 1; + m <<= 1; + StrnCpy(config[i].fname, str, m); + StrnCat(config[i++].fname, + CONFIG_EXTENSION, maxlen - m); + while (i <= nr) { + int stub = m - (i+1)*st; + StrnCpy(config[i].fname, str, stub); + StrnCat(config[i++].fname, + CONFIG_ARCH_EXTENSION, maxlen - m); + StrnCpy(config[i].fname, str, stub); + StrnCat(config[i++].fname, + CONFIG_EXTENSION, maxlen - m); + } + } + if (non_zero(info.hw_addr, 6)) { + convert_mac2hex(info.hw_addr,6,str); + StrnCpy(config[i].fname, str, maxlen-1); + StrnCpy(config[i++].fname+17, CONFIG_EXTENSION, 6); + } +#else StrnCpy(config[0].fname, str, maxlen-1); StrnCpy(config[0].fname+8, CONFIG_EXTENSION, 6); StrnCpy(config[1].fname, str, maxlen-1); - StrnCpy(config[1].fname+6, CONFIG_ARCH_EXTENSION, EXTENSION_LENGTH); + StrnCpy(config[1].fname+6, CONFIG_ARCH_EXTENSION, maxlen-7); StrnCpy(config[2].fname, str, maxlen-1); StrnCpy(config[2].fname+6, CONFIG_EXTENSION, 6); StrnCpy(config[3].fname, str, maxlen-1); - StrnCpy(config[3].fname+4, CONFIG_ARCH_EXTENSION, EXTENSION_LENGTH); + StrnCpy(config[3].fname+4, CONFIG_ARCH_EXTENSION, maxlen-5); StrnCpy(config[4].fname, str, maxlen-1); StrnCpy(config[4].fname+4, CONFIG_EXTENSION, 6); StrnCpy(config[5].fname, str, maxlen-1); - StrnCpy(config[5].fname+2, CONFIG_ARCH_EXTENSION, EXTENSION_LENGTH); + StrnCpy(config[5].fname+2, CONFIG_ARCH_EXTENSION, maxlen-3); StrnCpy(config[6].fname, str, maxlen-1); - StrnCpy(config[6].fname+2, CONFIG_EXTENSION, 6); + StrnCpy(config[6].fname+2, CONFIG_EXTENSION, maxlen-3); /* use the MAC address as a possible file name as well */ convert_mac2hex(info.hw_addr,6,str); StrnCpy(config[7].fname, str, maxlen-1); StrnCpy(config[7].fname+17, CONFIG_EXTENSION, 6); +#endif #else StrnCpy(config[0].fname, NETFS_DEFAULT_CONFIG, maxlen-1); --- a/strops.c +++ b/strops.c @@ -50,6 +50,17 @@ StrnCpy(OUT CHAR16 *dst, IN const CHAR16 return res; } +CHAR16 * +StrnCat(OUT CHAR16 *dst, IN const CHAR16 *src, IN UINTN size) +{ + CHAR16 *res; + + while (size && size-- && (*dst++) != CHAR_NULL); + res = StrnCpy(--dst, src, size); + + return res; +} + CHAR8 * StrnXCpy(OUT CHAR8 *dst, IN const CHAR16 *src, IN UINTN size) { --- a/strops.h +++ b/strops.h @@ -28,6 +28,7 @@ extern CHAR16 *StrChr(IN const CHAR16 *s, const CHAR16 c); extern CHAR16 *StrnCpy(OUT CHAR16 *dst, IN const CHAR16 *src, UINTN count); +extern CHAR16 *StrnCat(OUT CHAR16 *dst, IN const CHAR16 *src, UINTN count); extern CHAR8 *StrnXCpy(OUT CHAR8 *dst, IN const CHAR16 *src, UINTN count); extern CHAR8 *strtok_simple(CHAR8 *in, CHAR8 c); --- a/fs/netfs.c +++ b/fs/netfs.c @@ -75,6 +75,8 @@ typedef struct { EFI_IP_ADDRESS netmask; UINT8 hw_addr[16]; + CHAR8 bootfile[NETFS_BOOTFILE_MAXLEN]; + netfs_fd_t fd_tab[NETFS_FD_MAX]; netfs_fd_t *free_fd; UINTN free_fd_count; @@ -206,11 +208,239 @@ netfs_name(netfs_interface_t *this, CHAR return EFI_SUCCESS; } +typedef struct { + UINT16 code; + UINT16 len; + UINT8 data[]; +} DHCPv6_OPTION; + +#define DHCPv6_REPLY 7 +#define OPT_BOOTFILE_URL 59 +#define PROTO "tftp://" /* only TFTP supported for now */ + +static inline UINT16 +bswap16(UINT16 x) +{ + return ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)); +} +#if __BYTE_ORDER == __LITTLE_ENDIAN +# define ntohs(x) bswap16(x) +# define htons(x) bswap16(x) +#else +# if __BYTE_ORDER == __BIG_ENDIAN +# define ntohs(x) (x) +# define htons(x) (x) +# endif +#endif +/* string 2 net short */ +static UINT16 +stra2ns(CHAR8 *str) +{ + UINT16 ret = 0; + UINT8 v; + for(;*str;str++) { + if ('0' <= *str && *str <= '9') + v = *str - '0'; + else if ('A' <= *str && *str <= 'F') + v = *str - 'A' + 10; + else if ('a' <= *str && *str <= 'f') + v = *str - 'a' + 10; + else + v = 0; + ret = (ret << 4) + v; + } + /* DBG_PRT((L"stra2ns: '%a'='%d'", str, ret)); */ + return htons(ret); +} + +/* IPv4/6 address to string */ +static CHAR8 * +ip2stra(UINT8 octets, UINT8 *ip) +{ + int i, j; + static CHAR8 *hexa= (CHAR8 *)"0123456789ABCDEF"; + static CHAR8 str[42]; + + if (octets == 16) { + for(i=j=0; i < 16; i++) { + str[j++] = hexa[(ip[i] & 0xf0)>>4]; + str[j++] = hexa[ip[i] & 0x0f]; + if (i && i%2 == 0) + str[j++] = ':'; + } + } else if (octets == 4) { + int val, v; + for(i=j=0; i < 4; i++) { + val = ip[i]; + v = val / 100; + if (v) + str[j++] = '0' + v; + v = (val % 100) / 10; + if (v || val > 99) + str[j++] = '0' + v; + val %= 10; + str[j++] = '0' + val; + str[j++] = '.'; + } + } else + j = 1; + str[--j] = '\0'; + /* DBG_PRT((L"ip2stra: '%a'", str)); */ + return str; +} + +/* string 2 IPv6 address */ +static UINT8 * +stra2ip6(CHAR8 *str) +{ + UINTN i, j, p, len; + CHAR8 *a, *b, t; + static UINT16 ip[8]; + + for(i=0; i < 8; i++) { + ip[i] = 0; + } + len = strlena( str); + a = b = str; + for(i=p=0; i < len; i++, b++) { + if (*b != ':') + continue; + *b = '\0'; + ip[p++] = stra2ns(a); + *b = ':'; + a = b + 1; + if ( *(b+1) == ':' ) + break; + } + a = b = str + len; + for(j=len, p=7; j > i; j--, a--) { + if (*a != ':') + continue; + t = *b; + *b = '\0'; + ip[p--] = stra2ns(a+1); + *b = t; + b = a; + } + DBG_PRT((L"stra2ip6: '%a'='%a'", str, ip2stra(16, (UINT8 *)ip))); + return (UINT8 *)ip; +} + +static VOID +hexdump(UINT8 *dp, int size) +{ + int i = 0, j; + unsigned char *d = (unsigned char *)dp; + char hex[64], chr[17]; + static CHAR8 *hexa= (CHAR8 *)"0123456789ABCDEF"; + + hex[58] = '\0'; + chr[16] = '\0'; + while ( i < size ) { + if ( i > 0 && i % 16 == 0 ) + Print(L"%a >%a<\n", hex, chr); + if ( i % 16 == 0 ) { + Memset( hex, ' ', 58); + hex[56] = '\0'; + if (i>0xFFFFFF) return; + for (j = 0; j < 6; j++) + hex[j] = hexa[(i>>(4*(5-j))) & 0xF]; + } +#define pos(i) ((((i%16)<8)?8:9)+(i%16)*3) + hex[pos(i)] = hexa[d[i]>>4&0xF]; + hex[pos(i)+1] = hexa[d[i]&0xF]; + + chr[i%16] = ((d[i]>31&&d[i]<127)?d[i]:'.'); + i++; + } + if ( i % 16 != 1 ) { + chr[(i%16)] = '\0'; + Print(L"%a >%a<\n", hex, chr); + } +} + +static INTN +find_dhcp6_option( + EFI_PXE_BASE_CODE_PACKET *packet, + UINT8 option, + CHAR8 *str, + INTN *length) +{ + EFI_PXE_BASE_CODE_DHCPV6_PACKET *v6 = + (EFI_PXE_BASE_CODE_DHCPV6_PACKET *)packet->Raw; + int code, len; + DHCPv6_OPTION *p; + + /* Consistency check */ + if (v6->MessageType != DHCPv6_REPLY) { + VERB_PRT(2, Print(L"DHCPv6: MessageType: %d != %d\n", + v6->MessageType, DHCPv6_REPLY)); + VERB_PRT(3, hexdump( (UINT8 *)v6, 1024)); + return -1; + } + p = (DHCPv6_OPTION *)&v6->DhcpOptions; + while (0 != (code = ntohs(p->code))) { + len = ntohs(p->len); + + VERB_PRT(4, { Print(L"DHCPv6: REPLY: Code=%d Len=%d\n", + code, len); + hexdump( p->data, (len<1020)?len:144); + }); + if ( code == option ) { + len = (len > *length - 1) ? *length - 1 : len; + Memcpy(str, p->data, len); + str[len] = '\0'; + *length = len; + } + p = (DHCPv6_OPTION *)((UINT8 *)p + len + 2*sizeof(UINT16)); + } + return 0; +} +static INTN +parse_bootfile_url(netfs_priv_state_t *nfs, CHAR8 *url) { + CHAR8 *end; + VERB_PRT(3, Print(L"DHCPv6: bootfile-url: '%a'\n", url)); + + /* check protocol */ + if (strncmpa(url, (CHAR8 *)PROTO, sizeof(PROTO)-1)) { + ERR_PRT((L"Warning: bootfile-url must use TFTP for now! (%a)\n", + PROTO)); + return -1; + } + /* fill in v6 address */ + end = url+sizeof(PROTO); + while (*end != ']' && *end != '\0') + ++end; + if (url[sizeof(PROTO)-1] != '[' || *end != ']') { + ERR_PRT((L"Warning: bootfile-url must use '[IPv6::addr]'!\n")); + return -1; + } + *end = '\0'; + Memcpy( nfs->srv_ip.v6.Addr, stra2ip6(url+sizeof(PROTO)), 16); + *end = ']'; + + /* remember bootfile path */ + strncpya( nfs->bootfile, end + 1, NETFS_BOOTFILE_MAXLEN); + return 0; +} + static VOID netfs_extract_ip(netfs_priv_state_t *nfs) { EFI_PXE_BASE_CODE *pxe = nfs->pxe; + Memcpy(&nfs->cln_ip, &pxe->Mode->StationIp, sizeof(EFI_IP_ADDRESS)); + + if (pxe->Mode->UsingIpv6) { + CHAR8 str[NETFS_BOOTFILE_MAXLEN]; + INTN len = NETFS_BOOTFILE_MAXLEN; + if (find_dhcp6_option(&nfs->pxe->Mode->DhcpAck, + OPT_BOOTFILE_URL, str, &len) != 0) + return; + parse_bootfile_url(nfs, str); + return; + } + if (pxe->Mode->PxeDiscoverValid) { nfs->using_pxe = TRUE; Memcpy(&nfs->srv_ip, pxe->Mode->PxeReply.Dhcpv4.BootpSiAddr, sizeof(EFI_IP_ADDRESS)); @@ -218,9 +453,9 @@ netfs_extract_ip(netfs_priv_state_t *nfs } else { Memcpy(&nfs->srv_ip, pxe->Mode->DhcpAck.Dhcpv4.BootpSiAddr, sizeof(EFI_IP_ADDRESS)); Memcpy(&nfs->hw_addr, pxe->Mode->DhcpAck.Dhcpv4.BootpHwAddr, sizeof(nfs->hw_addr)); + strncpya(nfs->bootfile, pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile, NETFS_BOOTFILE_MAXLEN); } - Memcpy(&nfs->cln_ip, &pxe->Mode->StationIp, sizeof(EFI_IP_ADDRESS)); Memcpy(&nfs->netmask, &pxe->Mode->SubnetMask, sizeof(EFI_IP_ADDRESS)); /* @@ -326,11 +561,9 @@ netfs_open(netfs_interface_t *this, CHAR U2ascii(name, ascii_name, FILENAME_MAXLEN); - VERB_PRT(2, Print(L"downloading %a from %d.%d.%d.%d...\n", ascii_name, - nfs->srv_ip.v4.Addr[0], - nfs->srv_ip.v4.Addr[1], - nfs->srv_ip.v4.Addr[2], - nfs->srv_ip.v4.Addr[3])); + VERB_PRT(2, Print(L"downloading %a from %a...\n", ascii_name, + ip2stra((nfs->pxe->Mode->UsingIpv6 ? 16 : 4), + (UINT8 *)nfs->srv_ip.Addr))); retry: if (retries == 2) { netfs_fd_free(nfs, f); @@ -571,6 +804,9 @@ find_dhcp_option(EFI_PXE_BASE_CODE_PACKE UINT8 tag, length; UINT8 *opts = packet->Dhcpv4.DhcpOptions; + if (use_ipv6) + return find_dhcp6_option(packet, option, str, len); + *len = 0; for(;;) { @@ -637,15 +873,12 @@ netfs_getinfo(netfs_interface_t *this, n VERB_PRT(3, Print(L"hostname(12): %a\n", str)); - /* - * extract bootfile name from DHCP exchanges - */ - if (nfs->using_pxe == 0) { - ascii2U(nfs->pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile, info->bootfile, NETFS_BOOTFILE_MAXLEN); +skip_options: + if (!info->using_pxe && nfs->bootfile) { + ascii2U(nfs->bootfile, info->bootfile, NETFS_BOOTFILE_MAXLEN); VERB_PRT(3, Print(L"bootfile: %s\n", info->bootfile)); } -skip_options: return EFI_SUCCESS; }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor