void gaa_parser (int argc, char **argv) { if (gaa (argc, argv, &info) != -1) { fprintf (stderr, "Error in the arguments. Use the --help or -h parameters to get more information.\n"); exit (1); } verbose = info.verbose; disable_extensions = info.disable_extensions; print_cert = info.print_cert; starttls = info.starttls; resume = info.resume; rehandshake = info.rehandshake; insecure = info.insecure; service = info.port; record_max_size = info.record_size; fingerprint = info.fingerprint; if (info.fmtder == 0) x509ctype = GNUTLS_X509_FMT_PEM; else x509ctype = GNUTLS_X509_FMT_DER; srp_username = info.srp_username; srp_passwd = info.srp_passwd; x509_cafile = info.x509_cafile; x509_crlfile = info.x509_crlfile; x509_keyfile = info.x509_keyfile; x509_certfile = info.x509_certfile; pgp_keyfile = info.pgp_keyfile; pgp_certfile = info.pgp_certfile; psk_username = info.psk_username; psk_key.data = (unsigned char *) info.psk_key; if (info.psk_key != NULL) psk_key.size = strlen (info.psk_key); else psk_key.size = 0; pgp_keyring = info.pgp_keyring; crlf = info.crlf; if (info.rest_args == NULL) hostname = "localhost"; else hostname = info.rest_args; parse_protocols (info.proto, info.nproto, protocol_priority); parse_ciphers (info.ciphers, info.nciphers, cipher_priority); parse_macs (info.macs, info.nmacs, mac_priority); parse_ctypes (info.ctype, info.nctype, cert_type_priority); parse_kx (info.kx, info.nkx, kx_priority); parse_comp (info.comp, info.ncomp, comp_priority); }
int gaa_file(const char *name, gaainfo *gaaval) { gaa_str_node *first_str, **tmp_str, *tmp_str2; int rval, i; char **argv; int argc = 0; FILE *file; gaa_processing_file = 1; if((file = fopen(name, "r")) == NULL) { printf("Couldn't open '%s' configuration file for reading\n", name); return 1; } tmp_str = &first_str; do { argc++; *tmp_str = gaa_malloc(sizeof(gaa_str_node)); (*tmp_str)->str = NULL; (*tmp_str)->next = NULL; rval = gaa_internal_get_next_str(file, *tmp_str, argc); tmp_str = &((*tmp_str)->next); } while(rval == -1); if(rval == 1) return 0; argv = gaa_malloc((1 + argc) * sizeof(char*)); tmp_str2 = first_str; argv[0] = "cfg"; for(i = 1; i < argc; i++) { argv[i] = tmp_str2->str; tmp_str2 = tmp_str2->next; } rval = gaa(argc, argv, gaaval); gaa_processing_file = 0; return rval; }
int main(int argc, char **argv) { gaainfo info; int i, v; if((v = gaa_file("config", &info)) != -1) /* gets options from file 'config' */ { return 0; } if((v = gaa(argc, argv, &info)) != -1) { return 0; } printf("n : %d\nm : %d\nfile nf : %s %d\nverbose : %d\n", info.n, info.m, info.file,info.nf , info.verbose); if(info.size > 0) for(i = 0; i < info.size; i++) printf("%s\n", info.input[i]); return 0; }
int main (int argc, char **argv) { gaainfo info; int ret; struct passwd *pwd; unsigned char key[MAX_KEY_SIZE]; char hex_key[MAX_KEY_SIZE * 2 + 1]; gnutls_datum_t dkey; size_t hex_key_size = sizeof (hex_key); if ((ret = gnutls_global_init ()) < 0) { fprintf (stderr, "global_init: %s\n", gnutls_strerror (ret)); exit (1); } umask (066); if (gaa (argc, argv, &info) != -1) { fprintf (stderr, "Error in the arguments.\n"); return -1; } if (info.passwd == NULL) info.passwd = KPASSWD; if (info.username == NULL) { #ifndef _WIN32 pwd = getpwuid (getuid ()); if (pwd == NULL) { fprintf (stderr, "No such user\n"); return -1; } info.username = pwd->pw_name; #else fprintf (stderr, "Please specify a user\n"); return -1; #endif } if (info.key_size > MAX_KEY_SIZE) { fprintf (stderr, "Key size is too long\n"); exit (1); } if (info.netconf_hint) { char *passwd; if (info.key_size != 0 && info.key_size != 20) { fprintf (stderr, "For netconf, key size must always be 20.\n"); exit (1); } passwd = getpass ("Enter password: "******"Please specify a password\n"); exit (1); } ret = gnutls_psk_netconf_derive_key (passwd, info.username, info.netconf_hint, &dkey); } else { if (info.key_size < 1) info.key_size = 16; printf ("Generating a random key for user '%s'\n", info.username); ret = _gnutls_rnd (GNUTLS_RND_RANDOM, (char *) key, info.key_size); if (ret < 0) { fprintf (stderr, "Not enough randomness\n"); exit (1); } dkey.data = key; dkey.size = info.key_size; } ret = gnutls_hex_encode (&dkey, hex_key, &hex_key_size); if (info.netconf_hint) gnutls_free (dkey.data); if (ret < 0) { fprintf (stderr, "HEX encoding error\n"); exit (1); } ret = write_key (info.username, hex_key, hex_key_size, info.passwd); if (ret == 0) printf ("Key stored to %s\n", info.passwd); return ret; }
int main (int argc, char **argv) { gaainfo info; int ret; #ifndef _WIN32 struct passwd *pwd; #endif unsigned char key[MAX_KEY_SIZE]; char hex_key[MAX_KEY_SIZE * 2 + 1]; gnutls_datum_t dkey; size_t hex_key_size = sizeof (hex_key); set_program_name (argv[0]); if ((ret = gnutls_global_init ()) < 0) { fprintf (stderr, "global_init: %s\n", gnutls_strerror (ret)); exit (1); } umask (066); if (gaa (argc, argv, &info) != -1) { fprintf (stderr, "Error in the arguments.\n"); return -1; } if (info.passwd == NULL) info.passwd = (char *) KPASSWD; if (info.username == NULL) { #ifndef _WIN32 pwd = getpwuid (getuid ()); if (pwd == NULL) { fprintf (stderr, "No such user\n"); return -1; } info.username = pwd->pw_name; #else fprintf (stderr, "Please specify a user\n"); return -1; #endif } if (info.key_size > MAX_KEY_SIZE) { fprintf (stderr, "Key size is too long\n"); exit (1); } if (info.key_size < 1) info.key_size = 16; printf ("Generating a random key for user '%s'\n", info.username); ret = gnutls_rnd (GNUTLS_RND_RANDOM, (char *) key, info.key_size); if (ret < 0) { fprintf (stderr, "Not enough randomness\n"); exit (1); } dkey.data = key; dkey.size = info.key_size; ret = gnutls_hex_encode (&dkey, hex_key, &hex_key_size); if (ret < 0) { fprintf (stderr, "HEX encoding error\n"); exit (1); } ret = write_key (info.username, hex_key, hex_key_size, info.passwd); if (ret == 0) printf ("Key stored to %s\n", info.passwd); return ret; }
DWORD get_interfaces_windows(Remote *remote, Packet *response) { DWORD result = ERROR_SUCCESS; DWORD tlv_cnt; // Most of the time we'll need: // index, name (description), MAC addr, mtu, flags, IP addr, netmask, maybe scope id // In some cases, the interface will have multiple addresses, so we'll realloc // this when necessary, but this will cover the common case. DWORD allocd_entries = 20; Tlv *entries = (Tlv *)malloc(sizeof(Tlv) * 20); int prefixes[30]; int prefixes_cnt = 0; DWORD mtu_bigendian; DWORD interface_index_bigendian; ULONG flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_ANYCAST; LPSOCKADDR sockaddr; ULONG family = AF_UNSPEC; IP_ADAPTER_ADDRESSES *pAdapters = NULL; IP_ADAPTER_ADDRESSES *pCurr = NULL; ULONG outBufLen = 0; DWORD (WINAPI *gaa)(DWORD, DWORD, void *, void *, void *); // Use the newer version so we're guaranteed to have a large enough struct. // Unfortunately, using these probably means it won't compile on older // versions of Visual Studio. =( IP_ADAPTER_UNICAST_ADDRESS_LH *pAddr = NULL; IP_ADAPTER_UNICAST_ADDRESS_LH *pPref = NULL; // IP_ADAPTER_PREFIX is only defined if NTDDI_VERSION > NTDDI_WINXP // Since we request older versions of things, we have to be explicit // when using newer structs. IP_ADAPTER_PREFIX_XP *pPrefix = NULL; do { gaa = (DWORD (WINAPI *)(DWORD,DWORD,void*,void*,void*))GetProcAddress( GetModuleHandle("iphlpapi"), "GetAdaptersAddresses" ); if (!gaa) { result = get_interfaces_windows_mib(remote, response); break; } gaa(family, flags, NULL, pAdapters, &outBufLen); if (!(pAdapters = (IP_ADAPTER_ADDRESSES *)malloc(outBufLen))) { result = ERROR_NOT_ENOUGH_MEMORY; break; } if (gaa(family, flags, NULL, pAdapters, &outBufLen)) { result = GetLastError(); break; } // Enumerate the entries for (pCurr = pAdapters; pCurr; pCurr = pCurr->Next) { tlv_cnt = 0; interface_index_bigendian = htonl(pCurr->IfIndex); entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_INDEX; entries[tlv_cnt].buffer = (PUCHAR)&interface_index_bigendian; tlv_cnt++; entries[tlv_cnt].header.length = pCurr->PhysicalAddressLength; entries[tlv_cnt].header.type = TLV_TYPE_MAC_ADDR; entries[tlv_cnt].buffer = (PUCHAR)pCurr->PhysicalAddress; tlv_cnt++; entries[tlv_cnt].header.length = wcslen(pCurr->Description)*2 + 1; entries[tlv_cnt].header.type = TLV_TYPE_MAC_NAME; entries[tlv_cnt].buffer = (PUCHAR)pCurr->Description; tlv_cnt++; mtu_bigendian = htonl(pCurr->Mtu); entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_MTU; entries[tlv_cnt].buffer = (PUCHAR)&mtu_bigendian; tlv_cnt++; if (pCurr->Length > 68) { // Then this is a Longhorn struct version and it contains the // FirstPrefix member, save it for later in case we don't have // an OnLinkPrefixLength pPrefix = pCurr->FirstPrefix; } for (pAddr = (void*)pCurr->FirstUnicastAddress; pAddr; pAddr = (void*)pAddr->Next) { sockaddr = pAddr->Address.lpSockaddr; if (AF_INET != sockaddr->sa_family && AF_INET6 != sockaddr->sa_family) { // Skip interfaces that aren't IP continue; } // This loop can add up to three Tlv's - one for address, one // for scope_id, one for netmask. Go ahead and allocate enough // room for all of them. if (allocd_entries < tlv_cnt+3) { entries = realloc(entries, sizeof(Tlv) * (tlv_cnt+3)); allocd_entries += 3; } if (pAddr->Length > 44) { // Then this is Vista+ and the OnLinkPrefixLength member // will be populated prefixes[prefixes_cnt] = htonl(pAddr->OnLinkPrefixLength); } if (pPrefix && 0 == prefixes[prefixes_cnt]) { // Otherwise, we have to walk the FirstPrefix linked list prefixes[prefixes_cnt] = htonl(pPrefix->PrefixLength); pPrefix = pPrefix->Next; } else { // This is XP SP0 and as far as I can tell, we have no way // of determining the netmask short of bailing on // this method and falling back to MIB, which doesn't // return IPv6 addresses. Older versions (e.g. NT4, 2k) // don't have GetAdapterAddresses, so they will have fallen // through earlier to the MIB implementation. free(entries); free(pAdapters); return get_interfaces_windows_mib(remote, response); } if (prefixes[prefixes_cnt]) { entries[tlv_cnt].header.length = 4; entries[tlv_cnt].header.type = TLV_TYPE_IP_PREFIX; entries[tlv_cnt].buffer = (PUCHAR)&prefixes[prefixes_cnt]; tlv_cnt++; prefixes_cnt++; } if (sockaddr->sa_family == AF_INET) { entries[tlv_cnt].header.length = 4; entries[tlv_cnt].header.type = TLV_TYPE_IP; entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in *)sockaddr)->sin_addr); tlv_cnt++; } else { entries[tlv_cnt].header.length = 16; entries[tlv_cnt].header.type = TLV_TYPE_IP; entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_addr); tlv_cnt++; entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_IP6_SCOPE; entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_scope_id); tlv_cnt++; } } // Add the interface group packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE, entries, tlv_cnt); } } while (0); if (entries) free(entries); if (pAdapters) free(pAdapters); return result; }
int main (int argc, char **argv) { gaainfo info; const char *passwd; int salt_size, ret; #ifndef _WIN32 struct passwd *pwd; #endif set_program_name (argv[0]); if ((ret = gnutls_global_init ()) < 0) { fprintf (stderr, "global_init: %s\n", gnutls_strerror (ret)); exit (1); } umask (066); if (gaa (argc, argv, &info) != -1) { fprintf (stderr, "Error in the arguments.\n"); return -1; } gnutls_global_set_log_function (tls_log_func); gnutls_global_set_log_level (info.debug); if (info.create_conf != NULL) { return generate_create_conf (info.create_conf); } if (info.passwd == NULL) info.passwd = (char *) KPASSWD; if (info.passwd_conf == NULL) info.passwd_conf = (char *) KPASSWD_CONF; if (info.username == NULL) { #ifndef _WIN32 pwd = getpwuid (getuid ()); if (pwd == NULL) { fprintf (stderr, "No such user\n"); return -1; } info.username = pwd->pw_name; #else fprintf (stderr, "Please specify a user\n"); return -1; #endif } salt_size = 16; passwd = getpass ("Enter password: "******"Please specify a password\n"); return -1; } /* not ready yet */ if (info.verify != 0) { return verify_passwd (info.passwd_conf, info.passwd, info.username, passwd); } return crypt_int (info.username, passwd, salt_size, info.passwd_conf, info.passwd, info.index); }
static void gaa_parser (int argc, char **argv) { int ret; common_info_st cinfo; if (gaa (argc, argv, &info) != -1) { fprintf (stderr, "Try `%s --help' for more information.\n", program_name); exit (1); } gnutls_global_set_log_function (tls_log_func); gnutls_global_set_log_level (info.debug); if (info.debug > 1) printf ("Setting log level to %d\n", info.debug); if ((ret = gnutls_global_init ()) < 0) error (EXIT_FAILURE, 0, "global_init: %s", gnutls_strerror (ret)); if (info.pkcs11_provider != NULL) { ret = gnutls_pkcs11_init (GNUTLS_PKCS11_FLAG_MANUAL, NULL); if (ret < 0) fprintf (stderr, "pkcs11_init: %s", gnutls_strerror (ret)); else { ret = gnutls_pkcs11_add_provider (info.pkcs11_provider, NULL); if (ret < 0) error (EXIT_FAILURE, 0, "pkcs11_add_provider: %s", gnutls_strerror (ret)); } } else { ret = gnutls_pkcs11_init (GNUTLS_PKCS11_FLAG_AUTO, NULL); if (ret < 0) fprintf (stderr, "pkcs11_init: %s", gnutls_strerror (ret)); } if (info.outfile) { outfile = safe_open_rw (info.outfile, 0); if (outfile == NULL) error (EXIT_FAILURE, errno, "%s", info.outfile); } else outfile = stdout; memset (&cinfo, 0, sizeof (cinfo)); cinfo.secret_key = info.secret_key; cinfo.privkey = info.privkey; cinfo.pkcs8 = info.pkcs8; cinfo.incert_format = info.incert_format; cinfo.cert = info.cert; switch (info.action) { case ACTION_PKCS11_LIST: pkcs11_list (outfile, info.pkcs11_url, info.pkcs11_type, info.pkcs11_login, info.pkcs11_detailed_url, &cinfo); break; case ACTION_PKCS11_TOKENS: pkcs11_token_list (outfile, info.pkcs11_detailed_url, &cinfo); break; case ACTION_PKCS11_MECHANISMS: pkcs11_mechanism_list (outfile, info.pkcs11_url, info.pkcs11_login, &cinfo); break; case ACTION_PKCS11_EXPORT_URL: pkcs11_export (outfile, info.pkcs11_url, info.pkcs11_login, &cinfo); break; case ACTION_PKCS11_WRITE_URL: pkcs11_write (outfile, info.pkcs11_url, info.pkcs11_label, info.pkcs11_trusted, info.pkcs11_login, &cinfo); break; case ACTION_PKCS11_TOKEN_INIT: pkcs11_init (outfile, info.pkcs11_url, info.pkcs11_label, &cinfo); break; case ACTION_PKCS11_DELETE_URL: pkcs11_delete (outfile, info.pkcs11_url, 0, info.pkcs11_login, &cinfo); break; default: gaa_help (); exit (0); } fclose (outfile); gnutls_pkcs11_deinit (); gnutls_global_deinit (); }
int main (int argc, char **argv) { gaainfo info; const char *passwd; int salt, ret; struct passwd *pwd; if ((ret = gnutls_global_init ()) < 0) { fprintf (stderr, "global_init: %s\n", gnutls_strerror (ret)); exit (1); } #ifdef HAVE_UMASK umask (066); #endif if (gaa (argc, argv, &info) != -1) { fprintf (stderr, "Error in the arguments.\n"); return -1; } salt = info.salt; if (info.create_conf != NULL) { return generate_create_conf (info.create_conf); } if (info.passwd == NULL) info.passwd = KPASSWD; if (info.passwd_conf == NULL) info.passwd_conf = KPASSWD_CONF; if (info.username == NULL) { #ifndef _WIN32 pwd = getpwuid (getuid ()); if (pwd == NULL) { fprintf (stderr, "No such user\n"); return -1; } info.username = pwd->pw_name; #else fprintf (stderr, "Please specify a user\n"); return -1; #endif } salt = 16; passwd = getpass ("Enter password: "******"Please specify a password\n"); return -1; } /* not ready yet */ if (info.verify != 0) { return verify_passwd (info.passwd_conf, info.passwd, info.username, passwd); } return crypt_int (info.username, passwd, salt, info.passwd_conf, info.passwd, info.index); }
DWORD get_interfaces(Remote *remote, Packet *response) { DWORD result = ERROR_SUCCESS; ULONG flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_ANYCAST; LPSOCKADDR sockaddr; ULONG family = AF_UNSPEC; IP_ADAPTER_ADDRESSES *pAdapters = NULL; IP_ADAPTER_ADDRESSES *pCurr = NULL; ULONG outBufLen = 0; DWORD(WINAPI *gaa)(DWORD, DWORD, void *, void *, void *); // Use the newer version so we're guaranteed to have a large enough struct. // Unfortunately, using these probably means it won't compile on older // versions of Visual Studio. =( IP_ADAPTER_UNICAST_ADDRESS_LH *pAddr = NULL; IP_ADAPTER_UNICAST_ADDRESS_LH *pPref = NULL; // IP_ADAPTER_PREFIX is only defined if NTDDI_VERSION > NTDDI_WINXP // Since we request older versions of things, we have to be explicit // when using newer structs. IP_ADAPTER_PREFIX_XP *pPrefix = NULL; // We can't rely on the `Length` parameter of the IP_ADAPTER_PREFIX_XP struct // to tell us if we're on Vista or not because it always comes out at 48 bytes // so we have to check the version manually. OSVERSIONINFOEX v; gaa = (DWORD(WINAPI *)(DWORD, DWORD, void*, void*, void*))GetProcAddress( GetModuleHandle("iphlpapi"), "GetAdaptersAddresses"); if (!gaa) { dprintf("[INTERFACE] No 'GetAdaptersAddresses'. Falling back on get_interfaces_mib"); return get_interfaces_mib(remote, response); } gaa(family, flags, NULL, pAdapters, &outBufLen); if (!(pAdapters = malloc(outBufLen))) { return ERROR_NOT_ENOUGH_MEMORY; } if (gaa(family, flags, NULL, pAdapters, &outBufLen)) { result = GetLastError(); goto out; } dprintf("[INTERFACE] pAdapters->Length = %d", pAdapters->Length); // According to http://msdn.microsoft.com/en-us/library/windows/desktop/aa366058(v=vs.85).aspx // the PIP_ADAPTER_PREFIX doesn't exist prior to XP SP1. We check for this via the `Length` // value, which is 72 in XP without an SP, but 144 in later versions. if (pAdapters->Length <= 72) { dprintf("[INTERFACE] PIP_ADAPTER_PREFIX is missing"); result = get_interfaces_mib(remote, response); goto out; } // we'll need to know the version later on memset(&v, 0, sizeof(v)); v.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); GetVersionEx((LPOSVERSIONINFO)&v); // Enumerate the entries for (pCurr = pAdapters; pCurr; pCurr = pCurr->Next) { // Save the first prefix for later in case we don't have an OnLinkPrefixLength pPrefix = pCurr->FirstPrefix; Packet* group = packet_create_group(); dprintf("[INTERFACE] Adding index: %u", pCurr->IfIndex); packet_add_tlv_uint(group, TLV_TYPE_INTERFACE_INDEX, pCurr->IfIndex); dprintf("[INTERFACE] Adding MAC"); packet_add_tlv_raw(group, TLV_TYPE_MAC_ADDR, (PUCHAR)pCurr->PhysicalAddress, pCurr->PhysicalAddressLength); dprintf("[INTERFACE] Adding Description"); packet_add_tlv_wstring(group, TLV_TYPE_MAC_NAME, pCurr->Description); dprintf("[INTERFACE] Adding MTU: %u", pCurr->Mtu); packet_add_tlv_uint(group, TLV_TYPE_INTERFACE_MTU, pCurr->Mtu); for (pAddr = (IP_ADAPTER_UNICAST_ADDRESS_LH*)pCurr->FirstUnicastAddress; pAddr; pAddr = pAddr->Next) { sockaddr = pAddr->Address.lpSockaddr; if (AF_INET != sockaddr->sa_family && AF_INET6 != sockaddr->sa_family) { // Skip interfaces that aren't IP continue; } DWORD prefix = 0; if (v.dwMajorVersion >= 6) { // Then this is Vista+ and the OnLinkPrefixLength member // will be populated dprintf("[INTERFACES] >= Vista, using prefix: %x", pAddr->OnLinkPrefixLength); prefix = htonl(pAddr->OnLinkPrefixLength); } else if (pPrefix) { dprintf("[INTERFACES] < Vista, using prefix: %x", pPrefix->PrefixLength); prefix = htonl(pPrefix->PrefixLength); } else { dprintf("[INTERFACES] < Vista, no prefix"); prefix = 0; } if (prefix) { dprintf("[INTERFACE] Adding Prefix: %x", prefix); // the UINT value is already byte-swapped, so we add it as a raw instead of // swizzling the bytes twice. packet_add_tlv_raw(group, TLV_TYPE_IP_PREFIX, (PUCHAR)&prefix, sizeof(prefix)); } if (sockaddr->sa_family == AF_INET) { dprintf("[INTERFACE] Adding IPv4 Address: %x", ((struct sockaddr_in *)sockaddr)->sin_addr); packet_add_tlv_raw(group, TLV_TYPE_IP, (PUCHAR)&(((struct sockaddr_in *)sockaddr)->sin_addr), 4); } else { dprintf("[INTERFACE] Adding IPv6 Address"); packet_add_tlv_raw(group, TLV_TYPE_IP, (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_addr), 16); packet_add_tlv_raw(group, TLV_TYPE_IP6_SCOPE, (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_scope_id), sizeof(DWORD)); } } // Add the interface group packet_add_group(response, TLV_TYPE_NETWORK_INTERFACE, group); } out: free(pAdapters); return result; }