ibmi: Handle interface names longer than 10 chars
IBM i interface names are based off the associated line description. Since line descriptions are objects, they have 10 character limit on their names. However, since IBM i 7.2 interface names may be up to 16 characters long if the interface is for a a VLAN (eg. MYETHLINE1.4094). To handle this, we must strip off a VLAN ID to get the actual line description name, since that's what the QDCRLIND API wants. One issue exists because line descriptions can contain periods and numbers; so for interface names less than 10 characters long ETH2.4 could be a line description name or it could be ETH2 with VLAN 4. We follow the method that the XPF ioctls use: try the interface name directly first and if an error occurs, try to strip off the VLAN ID. https://www.ibm.com/docs/en/i/7.4?topic=ssw_ibm_i_74/apis/ioctl.htm#unotes Fixes: https://github.com/libuv/libuv/issues/3062 PR-URL: https://github.com/libuv/libuv/pull/3144 Reviewed-By: Richard Lau <rlau@redhat.com>
This commit is contained in:
parent
47e0c5c575
commit
af1a79cf49
@ -26,7 +26,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -166,7 +165,7 @@ static void iconv_a2e(const char* src, unsigned char dst[], size_t length) {
|
|||||||
|
|
||||||
srclen = strlen(src);
|
srclen = strlen(src);
|
||||||
if (srclen > length)
|
if (srclen > length)
|
||||||
abort();
|
srclen = length;
|
||||||
for (i = 0; i < srclen; i++)
|
for (i = 0; i < srclen; i++)
|
||||||
dst[i] = a2e[src[i]];
|
dst[i] = a2e[src[i]];
|
||||||
/* padding the remaining part with spaces */
|
/* padding the remaining part with spaces */
|
||||||
@ -360,6 +359,10 @@ static int get_ibmi_physical_address(const char* line, char (*phys_addr)[6]) {
|
|||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
if (err.bytes_available > 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* convert ebcdic loca_adapter_address to ascii first */
|
/* convert ebcdic loca_adapter_address to ascii first */
|
||||||
iconv_e2a(rcvr.loca_adapter_address, mac_addr,
|
iconv_e2a(rcvr.loca_adapter_address, mac_addr,
|
||||||
sizeof(rcvr.loca_adapter_address));
|
sizeof(rcvr.loca_adapter_address));
|
||||||
@ -443,9 +446,42 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
}
|
}
|
||||||
address->is_internal = cur->ifa_flags & IFF_LOOPBACK ? 1 : 0;
|
address->is_internal = cur->ifa_flags & IFF_LOOPBACK ? 1 : 0;
|
||||||
if (!address->is_internal) {
|
if (!address->is_internal) {
|
||||||
int rc = get_ibmi_physical_address(address->name, &address->phys_addr);
|
int rc = -1;
|
||||||
if (rc != 0)
|
size_t name_len = strlen(address->name);
|
||||||
r = rc;
|
/* To get the associated MAC address, we must convert the address to a
|
||||||
|
* line description. Normally, the name field contains the line
|
||||||
|
* description name, but for VLANs it has the VLAN appended with a
|
||||||
|
* period. Since object names can also contain periods and numbers, there
|
||||||
|
* is no way to know if a returned name is for a VLAN or not. eg.
|
||||||
|
* *LIND ETH1.1 and *LIND ETH1, VLAN 1 both have the same name: ETH1.1
|
||||||
|
*
|
||||||
|
* Instead, we apply the same heuristic used by some of the XPF ioctls:
|
||||||
|
* - names > 10 *must* contain a VLAN
|
||||||
|
* - assume names <= 10 do not contain a VLAN and try directly
|
||||||
|
* - if >10 or QDCRLIND returned an error, try to strip off a VLAN
|
||||||
|
* and try again
|
||||||
|
* - if we still get an error or couldn't find a period, leave the MAC as
|
||||||
|
* 00:00:00:00:00:00
|
||||||
|
*/
|
||||||
|
if (name_len <= 10) {
|
||||||
|
/* Assume name does not contain a VLAN ID */
|
||||||
|
rc = get_ibmi_physical_address(address->name, &address->phys_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name_len > 10 || rc != 0) {
|
||||||
|
/* The interface name must contain a VLAN ID suffix. Attempt to strip
|
||||||
|
* it off so we can get the line description to pass to QDCRLIND.
|
||||||
|
*/
|
||||||
|
char* temp_name = uv__strdup(address->name);
|
||||||
|
char* dot = strrchr(temp_name, '.');
|
||||||
|
if (dot != NULL) {
|
||||||
|
*dot = '\0';
|
||||||
|
if (strlen(temp_name) <= 10) {
|
||||||
|
rc = get_ibmi_physical_address(temp_name, &address->phys_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uv__free(temp_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
address++;
|
address++;
|
||||||
@ -498,4 +534,4 @@ int uv_get_process_title(char* buffer, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void uv__process_title_cleanup(void) {
|
void uv__process_title_cleanup(void) {
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user