1285
1265
LOAD_ATOM((spec), (i), (flag) ? am_true : am_false);
1286
1266
#endif /* HAVE_SCTP */
1268
/* Assume a cache line size of 64 bytes */
1269
#define INET_DRV_CACHE_LINE_SIZE ((ErlDrvUInt) 64)
1270
#define INET_DRV_CACHE_LINE_MASK (INET_DRV_CACHE_LINE_SIZE - 1)
1289
1273
** Binary Buffer Managment
1290
1274
** We keep a stack of usable buffers
1292
#define BUFFER_STACK_SIZE 16
1294
static erts_smp_spinlock_t inet_buffer_stack_lock;
1295
static ErlDrvBinary* buffer_stack[BUFFER_STACK_SIZE];
1296
static int buffer_stack_pos = 0;
1301
* The erts_smp_spin_* functions should not be used by drivers (but this
1302
* driver is special). Replace when driver locking api has been implemented.
1305
#define BUFSTK_LOCK erts_smp_spin_lock(&inet_buffer_stack_lock);
1306
#define BUFSTK_UNLOCK erts_smp_spin_unlock(&inet_buffer_stack_lock);
1309
static int tot_buf_allocated = 0; /* memory in use for i_buf */
1310
static int tot_buf_stacked = 0; /* memory on stack */
1311
static int max_buf_allocated = 0; /* max allocated */
1313
#define COUNT_BUF_ALLOC(sz) do { \
1315
tot_buf_allocated += (sz); \
1316
if (tot_buf_allocated > max_buf_allocated) \
1317
max_buf_allocated = tot_buf_allocated; \
1321
#define COUNT_BUF_FREE(sz) do { \
1323
tot_buf_allocated -= (sz); \
1327
#define COUNT_BUF_STACK(sz) do { \
1329
tot_buf_stacked += (sz); \
1335
#define COUNT_BUF_ALLOC(sz)
1336
#define COUNT_BUF_FREE(sz)
1337
#define COUNT_BUF_STACK(sz)
1276
#define BUFFER_STACK_SIZE 14
1277
#define BUFFER_STACK_MAX_MEM_SIZE (1024*1024)
1279
ErlDrvTSDKey buffer_stack_key;
1284
ErlDrvBinary* stk[BUFFER_STACK_SIZE];
1285
} InetDrvBufStkBase;
1288
InetDrvBufStkBase buf;
1289
char align[(((sizeof(InetDrvBufStkBase) - 1) / INET_DRV_CACHE_LINE_SIZE) + 1)
1290
* INET_DRV_CACHE_LINE_SIZE];
1293
static InetDrvBufStk *get_bufstk(void)
1295
InetDrvBufStk *bs = erl_drv_tsd_get(buffer_stack_key);
1298
bs = driver_alloc(sizeof(InetDrvBufStk)
1299
+ INET_DRV_CACHE_LINE_SIZE - 1);
1302
if ((((ErlDrvUInt) bs) & INET_DRV_CACHE_LINE_MASK) != 0)
1303
bs = ((InetDrvBufStk *)
1304
((((ErlDrvUInt) bs) & ~INET_DRV_CACHE_LINE_MASK)
1305
+ INET_DRV_CACHE_LINE_SIZE));
1306
erl_drv_tsd_set(buffer_stack_key, bs);
1308
bs->buf.mem_size = 0;
1310
ASSERT(bs == erl_drv_tsd_get(buffer_stack_key));
1341
1315
static ErlDrvBinary* alloc_buffer(long minsz)
1343
ErlDrvBinary* buf = NULL;
1347
DEBUGF(("alloc_buffer: sz = %ld, tot = %d, max = %d\r\n",
1348
minsz, tot_buf_allocated, max_buf_allocated));
1350
if (buffer_stack_pos > 0) {
1353
buf = buffer_stack[--buffer_stack_pos];
1354
origsz = buf->orig_size;
1356
COUNT_BUF_STACK(-origsz);
1357
if (origsz < minsz) {
1358
if ((buf = driver_realloc_binary(buf, minsz)) == NULL)
1360
COUNT_BUF_ALLOC(buf->orig_size - origsz);
1365
if ((buf = driver_alloc_binary(minsz)) == NULL)
1367
COUNT_BUF_ALLOC(buf->orig_size);
1317
InetDrvBufStk *bs = get_bufstk();
1319
DEBUGF(("alloc_buffer: %ld\r\n", minsz));
1321
if (bs && bs->buf.pos > 0) {
1323
ErlDrvBinary* buf = bs->buf.stk[--bs->buf.pos];
1324
size = buf->orig_size;
1325
bs->buf.mem_size -= size;
1326
ASSERT(0 <= bs->buf.mem_size
1327
&& bs->buf.mem_size <= BUFFER_STACK_MAX_MEM_SIZE);
1331
driver_free_binary(buf);
1334
ASSERT(!bs || bs->buf.pos != 0 || bs->buf.mem_size == 0);
1336
return driver_alloc_binary(minsz);
1373
** Max buffer memory "cached" BUFFER_STACK_SIZE * INET_MAX_BUFFER
1376
1339
/*#define CHECK_DOUBLE_RELEASE 1*/
1340
#ifdef CHECK_DOUBLE_RELEASE
1342
check_double_release(InetDrvBufStk *bs, ErlDrvBinary* buf)
1345
#warning CHECK_DOUBLE_RELEASE is enabled, this is a custom build emulator
1348
for (i = 0; i < bs->buf.pos; ++i) {
1349
if (bs->buf.stk[i] == buf) {
1350
erl_exit(ERTS_ABORT_EXIT,
1351
"Multiple buffer release in inet_drv, this "
1352
"is a bug, save the core and send it to "
1353
"support@erlang.ericsson.se!");
1377
1359
static void release_buffer(ErlDrvBinary* buf)
1379
1364
DEBUGF(("release_buffer: %ld\r\n", (buf==NULL) ? 0 : buf->orig_size));
1383
if ((buf->orig_size > INET_MAX_BUFFER) ||
1384
(buffer_stack_pos >= BUFFER_STACK_SIZE)) {
1386
COUNT_BUF_FREE(buf->orig_size);
1369
size = buf->orig_size;
1371
if (size > BUFFER_STACK_MAX_MEM_SIZE)
1376
|| (bs->buf.mem_size + size > BUFFER_STACK_MAX_MEM_SIZE)
1377
|| (bs->buf.pos >= BUFFER_STACK_SIZE)) {
1387
1379
driver_free_binary(buf);
1390
1382
#ifdef CHECK_DOUBLE_RELEASE
1392
#warning CHECK_DOUBLE_RELEASE is enabled, this is a custom build emulator
1395
for (i = 0; i < buffer_stack_pos; ++i) {
1396
if (buffer_stack[i] == buf) {
1397
erl_exit(1,"Multiple buffer release in inet_drv, this is a "
1398
"bug, save the core and send it to "
1399
"support@erlang.ericsson.se!");
1403
buffer_stack[buffer_stack_pos++] = buf;
1405
COUNT_BUF_STACK(buf->orig_size);
1383
check_double_release(bs, buf);
1385
ASSERT(bs->buf.pos != 0 || bs->buf.mem_size == 0);
1387
bs->buf.mem_size += size;
1388
bs->buf.stk[bs->buf.pos++] = buf;
1390
ASSERT(0 <= bs->buf.mem_size
1391
&& bs->buf.mem_size <= BUFFER_STACK_MAX_MEM_SIZE);
1409
1395
static ErlDrvBinary* realloc_buffer(ErlDrvBinary* buf, long newsz)
1413
long orig_size = buf->orig_size;
1416
if ((bin = driver_realloc_binary(buf,newsz)) != NULL) {
1417
COUNT_BUF_ALLOC(newsz - orig_size);
1397
return driver_realloc_binary(buf, newsz);
1423
1400
/* use a TRICK, access the refc field to see if any one else has
3862
3827
static char* sockaddr_to_buf(struct sockaddr* addr, char* ptr, char* end)
3864
3829
if (addr->sa_family == AF_INET || addr->sa_family == 0) {
3830
struct in_addr *p = &(((struct sockaddr_in*) addr)->sin_addr);
3831
buf_check(ptr, end, 1 + sizeof(struct in_addr));
3832
*ptr = INET_AF_INET;
3833
sys_memcpy(ptr+1, (char*)p, sizeof(struct in_addr));
3834
return ptr + 1 + sizeof(struct in_addr);
3836
#if defined(HAVE_IN6) && defined(AF_INET6)
3837
else if (addr->sa_family == AF_INET6) {
3838
struct in6_addr *p = &(((struct sockaddr_in6*) addr)->sin6_addr);
3839
buf_check(ptr, end, 1 + sizeof(struct in6_addr));
3840
*ptr = INET_AF_INET6;
3841
sys_memcpy(ptr+1, (char*)p, sizeof(struct in6_addr));
3842
return ptr + 1 + sizeof(struct in6_addr);
3845
#if defined(AF_LINK)
3846
else if (addr->sa_family == AF_LINK) {
3847
struct sockaddr_dl *sdl_p = (struct sockaddr_dl*) addr;
3848
buf_check(ptr, end, 2 + sdl_p->sdl_alen);
3849
put_int16(sdl_p->sdl_alen, ptr); ptr += 2;
3850
sys_memcpy(ptr, sdl_p->sdl_data + sdl_p->sdl_nlen, sdl_p->sdl_alen);
3851
return ptr + sdl_p->sdl_alen;
3854
#if defined(AF_PACKET) && defined(HAVE_NETPACKET_PACKET_H)
3855
else if(addr->sa_family == AF_PACKET) {
3856
struct sockaddr_ll *sll_p = (struct sockaddr_ll*) addr;
3857
buf_check(ptr, end, 2 + sll_p->sll_halen);
3858
put_int16(sll_p->sll_halen, ptr); ptr += 2;
3859
sys_memcpy(ptr, sll_p->sll_addr, sll_p->sll_halen);
3860
return ptr + sll_p->sll_halen;
3868
static char* buf_to_sockaddr(char* ptr, char* end, struct sockaddr* addr)
3870
buf_check(ptr,end,1);
3872
case INET_AF_INET: {
3873
struct in_addr *p = &((struct sockaddr_in*)addr)->sin_addr;
3866
3874
buf_check(ptr,end,sizeof(struct in_addr));
3867
a = ((struct sockaddr_in*) addr)->sin_addr;
3868
sys_memcpy(ptr, (char*)&a, sizeof(struct in_addr));
3875
sys_memcpy((char*) p, ptr, sizeof(struct in_addr));
3876
addr->sa_family = AF_INET;
3869
3877
return ptr + sizeof(struct in_addr);
3871
#if defined(HAVE_IN6) && defined(AF_INET6)
3872
else if (addr->sa_family == AF_INET6) {
3879
case INET_AF_INET6: {
3880
struct in6_addr *p = &((struct sockaddr_in6*)addr)->sin6_addr;
3874
3881
buf_check(ptr,end,sizeof(struct in6_addr));
3875
a = ((struct sockaddr_in6*) addr)->sin6_addr;
3876
sys_memcpy(ptr, (char*)&a, sizeof(struct in6_addr));
3882
sys_memcpy((char*) p, ptr, sizeof(struct in6_addr));
3883
addr->sa_family = AF_INET6;
3877
3884
return ptr + sizeof(struct in6_addr);
3892
#if defined (IFF_POINTOPOINT)
3893
#define IFGET_FLAGS(cflags) IFGET_FLAGS_P2P(cflags, IFF_POINTOPOINT)
3894
#elif defined IFF_POINTTOPOINT
3895
#define IFGET_FLAGS(cflags) IFGET_FLAGS_P2P(cflags, IFF_POINTTOPOINT)
3885
static char* buf_to_sockaddr(char* ptr, char* end, struct sockaddr* addr)
3887
buf_check(ptr,end,sizeof(struct in_addr));
3888
sys_memcpy((char*) &((struct sockaddr_in*)addr)->sin_addr, ptr,
3889
sizeof(struct in_addr));
3890
addr->sa_family = AF_INET;
3891
return ptr + sizeof(struct in_addr);
3898
#define IFGET_FLAGS_P2P(cflags, iff_ptp) \
3899
((((cflags) & IFF_UP) ? INET_IFF_UP : 0) | \
3900
(((cflags) & IFF_BROADCAST) ? INET_IFF_BROADCAST : 0) | \
3901
(((cflags) & IFF_LOOPBACK) ? INET_IFF_LOOPBACK : 0) | \
3902
(((cflags) & iff_ptp) ? INET_IFF_POINTTOPOINT : 0) | \
3903
(((cflags) & IFF_UP) ? INET_IFF_RUNNING : 0) | /* emulate running ? */ \
3904
(((cflags) & IFF_MULTICAST) ? INET_IFF_MULTICAST : 0))
3899
3906
#if defined(__WIN32__) && defined(SIO_GET_INTERFACE_LIST)
4462
/* Latin-1 to utf8 */
4464
static int utf8_len(const char *c, int m) {
4466
for (l = 0; m; c++, l++, m--) {
4467
if (*c == '\0') break;
4468
if ((*c & 0x7f) != *c) l++;
4473
static void utf8_encode(const char *c, int m, char *p) {
4474
for (; m; c++, m--) {
4475
if (*c == '\0') break;
4476
if ((*c & 0x7f) != *c) {
4477
*p++ = (char) (0xC0 | (0x03 & (*c >> 6)));
4478
*p++ = (char) (0x80 | (0x3F & *c));
4485
#if defined(__WIN32__)
4487
static void set_netmask_bytes(char *c, int len, int pref_len) {
4489
for (i = 0, m = pref_len >> 3; i < m && i < len; i++) c[i] = '\xFF';
4490
if (i < len) c[i++] = 0xFF << (8 - (pref_len & 7));
4491
for (; i < len; i++) c[i] = '\0';
4495
int eq_masked_bytes(char *a, char *b, int pref_len) {
4497
for (i = 0, m = pref_len >> 3; i < m; i++) {
4498
if (a[i] != b[i]) return 0;
4502
m = 0xFF & (0xFF << (8 - m));
4503
if ((a[i] & m) != (b[i] & m)) return 0;
4508
static int inet_ctl_getifaddrs(inet_descriptor* desc_p,
4509
char **rbuf_pp, int rsize)
4513
IP_INTERFACE_INFO *info_p;
4514
MIB_IPADDRTABLE *ip_addrs_p;
4515
IP_ADAPTER_ADDRESSES *ip_adaddrs_p, *ia_p;
4520
# define BUF_ENSURE(Size) \
4522
int NEED_, GOT_ = buf_p - buf_alloc_p; \
4523
NEED_ = GOT_ + (Size); \
4524
if (NEED_ > buf_size) { \
4525
buf_size = NEED_ + 512; \
4526
buf_alloc_p = REALLOC(buf_alloc_p, buf_size); \
4527
buf_p = buf_alloc_p + GOT_; \
4530
# define SOCKADDR_TO_BUF(opt, sa) \
4535
while (! (P_ = sockaddr_to_buf((sa), buf_p, \
4536
buf_alloc_p+buf_size))) { \
4537
int GOT_ = buf_p - buf_alloc_p; \
4539
buf_alloc_p = REALLOC(buf_alloc_p, buf_size); \
4540
buf_p = buf_alloc_p + GOT_; \
4542
if (P_ == buf_p) { \
4551
/* Try GetAdaptersAddresses, if it is available */
4552
unsigned long ip_adaddrs_size = 16 * 1024;
4553
ULONG family = AF_UNSPEC;
4555
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST |
4556
GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME |
4557
GAA_FLAG_SKIP_MULTICAST;
4558
ULONG (WINAPI *fpGetAdaptersAddresses)
4559
(ULONG, ULONG, PVOID, PIP_ADAPTER_ADDRESSES, PULONG);
4560
HMODULE iphlpapi = GetModuleHandle("iphlpapi");
4561
fpGetAdaptersAddresses = (void *)
4563
GetProcAddress(iphlpapi, "GetAdaptersAddresses") :
4565
if (fpGetAdaptersAddresses) {
4566
ip_adaddrs_p = ALLOC(ip_adaddrs_size);
4567
for (i = 17; i; i--) {
4568
ret = fpGetAdaptersAddresses(
4569
family, flags, NULL, ip_adaddrs_p, &ip_adaddrs_size);
4570
ip_adaddrs_p = REALLOC(ip_adaddrs_p, ip_adaddrs_size);
4571
if (ret == NO_ERROR) break;
4572
if (ret == ERROR_BUFFER_OVERFLOW) continue;
4577
ip_adaddrs_p = NULL;
4579
} else ip_adaddrs_p = NULL;
4583
/* Load the IP_INTERFACE_INFO table (only IPv4 interfaces),
4584
* reliable source of interface names on XP
4586
unsigned long info_size = 4 * 1024;
4587
info_p = ALLOC(info_size);
4588
for (i = 17; i; i--) {
4589
ret = GetInterfaceInfo(info_p, &info_size);
4590
info_p = REALLOC(info_p, info_size);
4591
if (ret == NO_ERROR) break;
4592
if (ret == ERROR_INSUFFICIENT_BUFFER) continue;
4601
if (! ip_adaddrs_p) {
4602
/* If GetAdaptersAddresses gave nothing we fall back to
4603
* MIB_IPADDRTABLE (only IPv4 interfaces)
4605
unsigned long ip_addrs_size = 16 * sizeof(*ip_addrs_p);
4606
ip_addrs_p = ALLOC(ip_addrs_size);
4607
for (i = 17; i; i--) {
4608
ret = GetIpAddrTable(ip_addrs_p, &ip_addrs_size, FALSE);
4609
ip_addrs_p = REALLOC(ip_addrs_p, ip_addrs_size);
4610
if (ret == NO_ERROR) break;
4611
if (ret == ERROR_INSUFFICIENT_BUFFER) continue;
4615
if (info_p) FREE(info_p);
4617
return ctl_reply(INET_REP_OK, NULL, 0, rbuf_pp, rsize);
4619
} else ip_addrs_p = NULL;
4621
buf_p = buf_alloc_p = ALLOC(buf_size);
4622
*buf_p++ = INET_REP_OK;
4624
/* Iterate over MIB_IPADDRTABLE or IP_ADAPTER_ADDRESSES */
4625
for (ia_p = NULL, ip_addrs_p ? ((void *)(i = 0)) : (ia_p = ip_adaddrs_p);
4626
ip_addrs_p ? (i < ip_addrs_p->dwNumEntries) : (ia_p != NULL);
4627
ip_addrs_p ? ((void *)(i++)) : (ia_p = ia_p->Next)) {
4628
MIB_IPADDRROW *ipaddrrow_p = NULL;
4629
DWORD flags = INET_IFF_MULTICAST;
4631
WCHAR *wname_p = NULL;
4635
ipaddrrow_p = ip_addrs_p->table + i;
4636
index = ipaddrrow_p->dwIndex;
4638
index = ia_p->IfIndex;
4639
if (ia_p->Flags & IP_ADAPTER_NO_MULTICAST) {
4640
flags &= ~INET_IFF_MULTICAST;
4644
if (! index) goto done;
4645
sys_memzero(&ifrow, sizeof(ifrow));
4646
ifrow.dwIndex = index;
4647
if (GetIfEntry(&ifrow) != NO_ERROR) break;
4648
/* Find the interface name - first try MIB_IFROW.wzname */
4649
if (ifrow.wszName[0] != 0) {
4650
wname_p = ifrow.wszName;
4652
/* Then try IP_ADAPTER_INDEX_MAP.Name (only IPv4 adapters) */
4654
for (j = 0; j < info_p->NumAdapters; j++) {
4655
if (info_p->Adapter[j].Index == (ULONG) ifrow.dwIndex) {
4656
if (info_p->Adapter[j].Name[0] != 0) {
4657
wname_p = info_p->Adapter[j].Name;
4665
/* Convert interface name to UTF-8 */
4667
WideCharToMultiByte(
4668
CP_UTF8, 0, wname_p, -1, NULL, 0, NULL, NULL);
4671
WideCharToMultiByte(
4672
CP_UTF8, 0, wname_p, -1, buf_p, len, NULL, NULL);
4676
* use "MIB_IFROW.dwIndex: MIB_IFROW.bDescr" as name instead */
4678
l = utf8_len(ifrow.bDescr, ifrow.dwDescrLen);
4679
BUF_ENSURE(9 + l+1);
4682
buf_p, "%lu: ", (unsigned long) ifrow.dwIndex);
4683
utf8_encode(ifrow.bDescr, ifrow.dwDescrLen, buf_p);
4687
/* Interface flags, often make up broadcast and multicast flags */
4688
switch (ifrow.dwType) {
4689
case IF_TYPE_ETHERNET_CSMACD:
4690
flags |= INET_IFF_BROADCAST;
4692
case IF_TYPE_SOFTWARE_LOOPBACK:
4693
flags |= INET_IFF_LOOPBACK;
4694
flags &= ~INET_IFF_MULTICAST;
4697
flags &= ~INET_IFF_MULTICAST;
4700
if (ifrow.dwAdminStatus) {
4701
flags |= INET_IFF_UP;
4702
switch (ifrow.dwOperStatus) {
4703
case IF_OPER_STATUS_CONNECTING:
4704
flags |= INET_IFF_POINTTOPOINT;
4706
case IF_OPER_STATUS_CONNECTED:
4707
flags |= INET_IFF_RUNNING | INET_IFF_POINTTOPOINT;
4709
case IF_OPER_STATUS_OPERATIONAL:
4710
flags |= INET_IFF_RUNNING;
4715
*buf_p++ = INET_IFOPT_FLAGS;
4716
put_int32(flags, buf_p); buf_p += 4;
4718
/* Legacy implementation through GetIpAddrTable */
4719
struct sockaddr_in sin;
4721
sys_memzero(&sin, sizeof(sin));
4722
sin.sin_family = AF_INET;
4723
sin.sin_addr.s_addr = ipaddrrow_p->dwAddr;
4726
SOCKADDR_TO_BUF(INET_IFOPT_ADDR, (struct sockaddr *) &sin);
4727
sin.sin_addr.s_addr = ipaddrrow_p->dwMask;
4729
SOCKADDR_TO_BUF(INET_IFOPT_NETMASK, (struct sockaddr *) &sin);
4730
if (flags & INET_IFF_BROADCAST) {
4731
/* Broadcast address - fake it*/
4732
sin.sin_addr.s_addr = ipaddrrow_p->dwAddr;
4733
sin.sin_addr.s_addr |= ~ipaddrrow_p->dwMask;
4736
INET_IFOPT_BROADADDR, (struct sockaddr *) &sin);
4739
IP_ADAPTER_UNICAST_ADDRESS *p;
4740
/* IP Address(es) */
4741
for (p = ia_p->FirstUnicastAddress;
4745
IP_ADAPTER_PREFIX *q;
4746
ULONG shortest_length;
4747
struct sockaddr *shortest_p, *sa_p = p->Address.lpSockaddr;
4749
SOCKADDR_TO_BUF(INET_IFOPT_ADDR, sa_p);
4751
shortest_length = 0;
4752
for (q = ia_p->FirstPrefix;
4755
struct sockaddr *sp_p = q->Address.lpSockaddr;
4756
if (sa_p->sa_family != sp_p->sa_family) continue;
4757
switch (sa_p->sa_family) {
4759
struct sockaddr_in sin;
4762
((struct sockaddr_in *)
4763
sa_p)->sin_addr.s_addr);
4765
((struct sockaddr_in *)
4766
sp_p)->sin_addr.s_addr);
4767
mask = 0xFFFFFFFF << (32 - q->PrefixLength);
4768
if ((sa & mask) != (sp & mask)) continue;
4770
|| q->PrefixLength < shortest_length) {
4772
shortest_length = q->PrefixLength;
4776
struct sockaddr_in6 sin6;
4777
if (!eq_masked_bytes((char *)
4778
&((struct sockaddr_in6 *)
4781
&((struct sockaddr_in6 *)
4787
|| q->PrefixLength < shortest_length) {
4789
shortest_length = q->PrefixLength;
4795
/* Found no shortest prefix */
4797
switch (shortest_p->sa_family) {
4799
/* Fall back to old classfull network addresses */
4800
DWORD addr = ntohl(((struct sockaddr_in *)shortest_p)
4802
if (! (addr & 0x800000)) {
4804
shortest_length = 8;
4805
} else if (! (addr & 0x400000)) {
4807
shortest_length = 16;
4808
} else if (! (addr & 0x200000)) {
4810
shortest_length = 24;
4812
shortest_length = 32;
4816
/* Just play it safe */
4817
shortest_length = 128;
4821
switch (shortest_p->sa_family) {
4823
struct sockaddr_in sin;
4824
DWORD mask = 0xFFFFFFFF << (32 - shortest_length);
4825
sys_memzero(&sin, sizeof(sin));
4826
sin.sin_family = shortest_p->sa_family;
4827
sin.sin_addr.s_addr = htonl(mask);
4829
SOCKADDR_TO_BUF(INET_IFOPT_NETMASK,
4830
(struct sockaddr *) &sin);
4831
if (flags & INET_IFF_BROADCAST) {
4834
((struct sockaddr_in *)shortest_p)
4835
-> sin_addr.s_addr);
4836
sin.sin_addr.s_addr = htonl(sp | ~mask);
4838
SOCKADDR_TO_BUF(INET_IFOPT_BROADADDR,
4839
(struct sockaddr *) &sin);
4843
struct sockaddr_in6 sin6;
4844
sys_memzero(&sin6, sizeof(sin6));
4845
sin6.sin6_family = shortest_p->sa_family;
4846
set_netmask_bytes((char *) &sin6.sin6_addr,
4850
SOCKADDR_TO_BUF(INET_IFOPT_NETMASK,
4851
(struct sockaddr *) &sin6);
4856
if (ifrow.dwPhysAddrLen) {
4857
/* Hardware Address */
4858
BUF_ENSURE(1 + 2 + ifrow.dwPhysAddrLen);
4859
*buf_p++ = INET_IFOPT_HWADDR;
4860
put_int16(ifrow.dwPhysAddrLen, buf_p); buf_p += 2;
4861
sys_memcpy(buf_p, ifrow.bPhysAddr, ifrow.dwPhysAddrLen);
4862
buf_p += ifrow.dwPhysAddrLen;
4866
/* That is all for this interface */
4870
ia_p->Ipv6IfIndex &&
4871
ia_p->Ipv6IfIndex != index)
4873
/* Oops, there was an other interface for IPv6. Possible? XXX */
4874
index = ia_p->Ipv6IfIndex;
4879
if (ip_adaddrs_p) FREE(ip_adaddrs_p);
4880
if (info_p) FREE(info_p);
4881
if (ip_addrs_p) FREE(ip_addrs_p);
4883
buf_size = buf_p - buf_alloc_p;
4884
buf_alloc_p = REALLOC(buf_alloc_p, buf_size);
4885
/* buf_p is now unreliable */
4886
*rbuf_pp = buf_alloc_p;
4891
#elif defined(HAVE_GETIFADDRS)
4893
static int inet_ctl_getifaddrs(inet_descriptor* desc_p,
4894
char **rbuf_pp, int rsize)
4896
struct ifaddrs *ifa_p, *ifa_free_p;
4903
buf_alloc_p = ALLOC(buf_size);
4904
buf_p = buf_alloc_p;
4905
# define BUF_ENSURE(Size) \
4907
int NEED_, GOT_ = buf_p - buf_alloc_p; \
4908
NEED_ = GOT_ + (Size); \
4909
if (NEED_ > buf_size) { \
4910
buf_size = NEED_ + 512; \
4911
buf_alloc_p = REALLOC(buf_alloc_p, buf_size); \
4912
buf_p = buf_alloc_p + GOT_; \
4915
# define SOCKADDR_TO_BUF(opt, sa) \
4920
while (! (P_ = sockaddr_to_buf((sa), buf_p, \
4921
buf_alloc_p+buf_size))) { \
4922
int GOT_ = buf_p - buf_alloc_p; \
4924
buf_alloc_p = REALLOC(buf_alloc_p, buf_size); \
4925
buf_p = buf_alloc_p + GOT_; \
4927
if (P_ == buf_p) { \
4935
if (getifaddrs(&ifa_p) < 0) {
4936
return ctl_error(sock_errno(), rbuf_pp, rsize);
4939
*buf_p++ = INET_REP_OK;
4940
for (; ifa_p; ifa_p = ifa_p->ifa_next) {
4941
int len = utf8_len(ifa_p->ifa_name, -1);
4942
BUF_ENSURE(len+1 + 1+4 + 1);
4943
utf8_encode(ifa_p->ifa_name, -1, buf_p);
4946
*buf_p++ = INET_IFOPT_FLAGS;
4947
put_int32(IFGET_FLAGS(ifa_p->ifa_flags), buf_p); buf_p += 4;
4948
if (ifa_p->ifa_addr) {
4949
if (ifa_p->ifa_addr->sa_family == AF_INET
4950
#if defined(AF_INET6)
4951
|| ifa_p->ifa_addr->sa_family == AF_INET6
4954
SOCKADDR_TO_BUF(INET_IFOPT_ADDR, ifa_p->ifa_addr);
4955
if (ifa_p->ifa_netmask) {
4957
SOCKADDR_TO_BUF(INET_IFOPT_NETMASK, ifa_p->ifa_netmask);
4959
if (ifa_p->ifa_dstaddr &&
4960
(ifa_p->ifa_flags & IFF_POINTOPOINT)) {
4962
SOCKADDR_TO_BUF(INET_IFOPT_DSTADDR, ifa_p->ifa_dstaddr);
4963
} else if (ifa_p->ifa_broadaddr &&
4964
(ifa_p->ifa_flags & IFF_BROADCAST)) {
4966
SOCKADDR_TO_BUF(INET_IFOPT_BROADADDR, ifa_p->ifa_broadaddr);
4969
#if defined(AF_LINK) || defined(AF_PACKET)
4971
#if defined(AF_LINK)
4972
ifa_p->ifa_addr->sa_family == AF_LINK
4976
#if defined(AF_PACKET)
4977
|| ifa_p->ifa_addr->sa_family == AF_PACKET
4982
SOCKADDR_TO_BUF(INET_IFOPT_HWADDR, ifa_p->ifa_addr);
4983
if (buf_p - bp < 4) buf_p = bp; /* Empty hwaddr */
4990
buf_size = buf_p - buf_alloc_p;
4991
buf_alloc_p = REALLOC(buf_alloc_p, buf_size);
4992
/* buf_p is now unreliable */
4993
freeifaddrs(ifa_free_p);
4994
*rbuf_pp = buf_alloc_p;
5001
static int inet_ctl_getifaddrs(inet_descriptor* desc_p,
5002
char **rbuf_pp, int rsize)
5004
return ctl_error(ENOTSUP, rbuf_pp, rsize);
4432
5013
** THIS is a terrible creature, a bug in the TCP part