XS-libuv

 view release on metacpan or  search on metacpan

libuv-1.49.2/src/unix/ibmi.c  view on Meta::CPAN


  /* qwcrssts_argv is the array of argument pointers to QDCRLIND */
  void* qdcrlind_argv[6];

  /* Set the IBM i pointer to the QSYS/QDCRLIND *PGM object */
  int rc = _RSLOBJ2(&qdcrlind_pointer, RSLOBJ_TS_PGM, "QDCRLIND", "QSYS");

  if (rc != 0)
    return rc;

  /* initialize the QDCRLIND returned info structure */
  memset(&rcvr, 0, sizeof(rcvr));

  /* initialize the QDCRLIND error code structure */
  memset(&err, 0, sizeof(err));
  err.bytes_provided = sizeof(err);

  /* initialize the array of argument pointers for the QDCRLIND API */
  qdcrlind_argv[0] = &rcvr;
  qdcrlind_argv[1] = &rcvrlen;
  qdcrlind_argv[2] = &format;
  qdcrlind_argv[3] = &line_name;
  qdcrlind_argv[4] = &err;
  qdcrlind_argv[5] = NULL;

  /* Call the IBM i QDCRLIND API from PASE */
  rc = _PGMCALL(&qdcrlind_pointer, qdcrlind_argv, 0);
  if (rc != 0)
    return rc;

  if (err.bytes_available > 0) {
    return -1;
  }

  /* convert ebcdic loca_adapter_address to ascii first */
  iconv_e2a(rcvr.loca_adapter_address, mac_addr,
            sizeof(rcvr.loca_adapter_address));

  /* convert loca_adapter_address(char[12]) to phys_addr(char[6]) */
  int r = sscanf(mac_addr, "%02x%02x%02x%02x%02x%02x",
                &c[0], &c[1], &c[2], &c[3], &c[4], &c[5]);

  if (r == ARRAY_SIZE(c)) {
    (*phys_addr)[0] = c[0];
    (*phys_addr)[1] = c[1];
    (*phys_addr)[2] = c[2];
    (*phys_addr)[3] = c[3];
    (*phys_addr)[4] = c[4];
    (*phys_addr)[5] = c[5];
  } else {
    memset(*phys_addr, 0, sizeof(*phys_addr));
    rc = -1;
  }
  return rc;
}


int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
  uv_interface_address_t* address;
  struct ifaddrs_pase *ifap = NULL, *cur;
  int inet6, r = 0;

  *count = 0;
  *addresses = NULL;

  if (Qp2getifaddrs(&ifap))
    return UV_ENOSYS;

  /* The first loop to get the size of the array to be allocated */
  for (cur = ifap; cur; cur = cur->ifa_next) {
    if (!(cur->ifa_addr->sa_family == AF_INET6 ||
          cur->ifa_addr->sa_family == AF_INET))
      continue;

    if (!(cur->ifa_flags & IFF_UP && cur->ifa_flags & IFF_RUNNING))
      continue;

    (*count)++;
  }

  if (*count == 0) {
    Qp2freeifaddrs(ifap);
    return 0;
  }

  /* Alloc the return interface structs */
  *addresses = uv__calloc(*count, sizeof(**addresses));
  if (*addresses == NULL) {
    Qp2freeifaddrs(ifap);
    return UV_ENOMEM;
  }
  address = *addresses;

  /* The second loop to fill in the array */
  for (cur = ifap; cur; cur = cur->ifa_next) {
    if (!(cur->ifa_addr->sa_family == AF_INET6 ||
          cur->ifa_addr->sa_family == AF_INET))
      continue;

    if (!(cur->ifa_flags & IFF_UP && cur->ifa_flags & IFF_RUNNING))
      continue;

    address->name = uv__strdup(cur->ifa_name);

    inet6 = (cur->ifa_addr->sa_family == AF_INET6);

    if (inet6) {
      address->address.address6 = *((struct sockaddr_in6*)cur->ifa_addr);
      address->netmask.netmask6 = *((struct sockaddr_in6*)cur->ifa_netmask);
      address->netmask.netmask6.sin6_family = AF_INET6;
    } else {
      address->address.address4 = *((struct sockaddr_in*)cur->ifa_addr);
      address->netmask.netmask4 = *((struct sockaddr_in*)cur->ifa_netmask);
      address->netmask.netmask4.sin_family = AF_INET;
    }
    address->is_internal = cur->ifa_flags & IFF_LOOPBACK ? 1 : 0;
    if (!address->is_internal) {
      int rc = -1;
      size_t name_len = strlen(address->name);
      /* 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++;
  }

  Qp2freeifaddrs(ifap);
  return r;
}


void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) {
  int i;

  for (i = 0; i < count; ++i) {



( run in 0.472 second using v1.01-cache-2.11-cpan-437f7b0c052 )