~ubuntu-branches/ubuntu/natty/ntop/natty

« back to all changes in this revision

Viewing changes to iface.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2005-01-30 21:59:13 UTC
  • mfrom: (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20050130215913-xc3ke963bw49b3k4
Tags: 2:3.0-5
* Updated README.Debian file so users will understand what to do at
  install, closes: #291794, #287802.
* Updated ntop init script to give better output.
* Also changed log directory from /var/lib/ntop to /var/log/ntop,
  closes: #252352.
* Quoted the interface list to allow whitespace, closes: #267248.
* Added a couple of logcheck ignores, closes: #269321, #269319.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
3
 *                          http://www.ntop.org
 
4
 *
 
5
 * Copyright (C) 2003      Abdelkader Lahmadi <Abdelkader.Lahmadi@loria.fr>
 
6
 *                         Olivier Festor <Olivier.Festor@loria.fr>
 
7
 * Copyright (C) 2003-04   Luca Deri <deri@ntop.org>
 
8
 *
 
9
 * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
10
 *
 
11
 * This program is free software; you can redistribute it and/or modify
 
12
 * it under the terms of the GNU General Public License as published by
 
13
 * the Free Software Foundation; either version 2 of the License, or
 
14
 * (at your option) any later version.
 
15
 *
 
16
 * This program is distributed in the hope that it will be useful,
 
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
 * GNU General Public License for more details.
 
20
 *
 
21
 * You should have received a copy of the GNU General Public License
 
22
 * along with this program; if not, write to the Free Software Foundation,
 
23
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
24
 */
 
25
 
 
26
#include "ntop.h"
 
27
 
 
28
#ifdef INET6
 
29
 
 
30
#define ROUNDUP(a) \
 
31
        ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
 
32
 
 
33
#define SA(saddr)       ((struct sockaddr *)saddr)
 
34
#define SA4(saddr)      ((struct sockaddr_in *)saddr)
 
35
#define IN4(saddr)      (&SA4(saddr)->sin_addr)
 
36
#define SA6(saddr)      ((struct sockaddr_in6 *)saddr)
 
37
#define IN6(saddr)      (&SA6(saddr)->sin6_addr)
 
38
 
 
39
 
 
40
static struct in6_addr *in6_cpy(struct in6_addr *dst, struct in6_addr *src) {
 
41
  return memcpy(dst, src, sizeof(struct in6_addr));
 
42
}
 
43
 
 
44
static struct in_addr *in4_cpy(struct in_addr *dst, struct in_addr *src) {
 
45
  return memcpy(dst, src, sizeof(struct in_addr));
 
46
}
 
47
 
 
48
static str2in6_addr(char *str, struct in6_addr *addr){
 
49
  int i;
 
50
  unsigned int x;
 
51
 
 
52
  for (i=0; i < 16; i++){
 
53
    sscanf(str + (i*2), "%02x",&x);
 
54
    addr->s6_addr[i]= x & 0xff;
 
55
  }
 
56
}
 
57
static int prefixlen(void *val, int size) {
 
58
  unsigned char *name = (unsigned char *)val;
 
59
  int byte, bit, plen = 0;
 
60
 
 
61
  for (byte = 0; byte < size; byte++, plen += 8)
 
62
    if (name[byte] != 0xff)
 
63
      break;
 
64
  if (byte == size)
 
65
    return (plen);
 
66
  for (bit = 7; bit != 0; bit--, plen++)
 
67
    if (!(name[byte] & (1 << bit)))
 
68
      break;
 
69
  for (; bit != 0; bit--)
 
70
    if (name[byte] & (1 << bit))
 
71
      return(0);
 
72
  byte++;
 
73
  for (; byte < size; byte++)
 
74
    if (name[byte])
 
75
      return(0);
 
76
  return (plen);
 
77
}
 
78
 
 
79
/* ************************************************* */
 
80
 
 
81
#if defined(HAVE_IFLIST_SYSCTL) && defined(HAVE_SYSCTL)
 
82
 
 
83
struct iface_handler *iface_new(void) {
 
84
  int            mib[6] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
 
85
  char          *buf = NULL;
 
86
  char          *lim, *next;
 
87
  size_t                 needed;
 
88
  struct iface_handler *hdlr = NULL;
 
89
  int i;
 
90
  int if_pos = 0;
 
91
  int addr_pos = 0;
 
92
  struct iface_addr     *ia;
 
93
 
 
94
  /* Allocate memory for iface handler
 
95
   */
 
96
  if (! (hdlr = (struct iface_handler *)calloc(1,sizeof(struct iface_handler)))) {
 
97
    errno = ENOMEM;
 
98
    goto failed;
 
99
  }
 
100
 
 
101
  /* Retrieve raw interface information buffer
 
102
   */
 
103
  if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
 
104
    goto failed;
 
105
  if (! (buf = malloc(needed))) {
 
106
    errno = ENOMEM;
 
107
    goto failed;
 
108
  }
 
109
  if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
 
110
    goto failed;
 
111
 
 
112
 
 
113
  /* Count interfaces and addresses
 
114
   */
 
115
  lim  = buf + needed;
 
116
  next = buf;
 
117
  while (next < lim) {
 
118
    struct if_msghdr *ifm = (struct if_msghdr *)next;
 
119
    if (ifm->ifm_type != RTM_IFINFO)
 
120
      goto failed;
 
121
    hdlr->if_count++;
 
122
    next += ifm->ifm_msglen;
 
123
    while (next < lim) {
 
124
      struct if_msghdr *nextifm = (struct if_msghdr *)next;
 
125
      if (nextifm->ifm_type != RTM_NEWADDR)
 
126
        break;
 
127
      next += nextifm->ifm_msglen;
 
128
      hdlr->addr_count++;
 
129
    }
 
130
  }
 
131
 
 
132
 
 
133
  /* Allocate memory for storing interfaces/addresses lists
 
134
   */
 
135
  if ((! (hdlr->if_list   = (struct iface_if *)calloc(hdlr->if_count,sizeof(struct iface_if)))) ||
 
136
      (! (hdlr->addr_list = (struct iface_addr *)calloc(hdlr->addr_count,sizeof(struct iface_addr))))) {
 
137
    errno = ENOMEM;
 
138
    goto failed;
 
139
  }
 
140
 
 
141
 
 
142
  /* Parsing raw buffer
 
143
   */
 
144
  lim  = buf + needed;
 
145
  next = buf;
 
146
  while (next < lim) {
 
147
    struct iface_if             *ii     = &hdlr->if_list[if_pos];
 
148
    struct if_msghdr    *ifm    = (struct if_msghdr *)next;
 
149
    struct sockaddr_dl  *sdl    = (struct sockaddr_dl *)(ifm + 1);
 
150
    int                  acount = 0;
 
151
 
 
152
    /* Sanity check
 
153
     */
 
154
    if (ifm->ifm_type != RTM_IFINFO) {
 
155
      errno = EACCES;
 
156
      goto failed;
 
157
    }
 
158
 
 
159
    /* Interface name and index
 
160
     */
 
161
    ii->next = &hdlr->if_list[if_pos+1];
 
162
 
 
163
    ii->index = ifm->ifm_index;
 
164
    strncpy(ii->name, sdl->sdl_data, sdl->sdl_nlen);
 
165
    ii->name[sdl->sdl_nlen] = '\0';
 
166
 
 
167
    /* Interface info
 
168
     *  UP / BROADCAST / MULTICAST / LOOPBACK / P2P / PROMISC / SIMPLEX
 
169
     */
 
170
    if (ifm->ifm_flags & IFF_UP)                /* interface is UP      */
 
171
      ii->info |= IFACE_INFO_UP;
 
172
    if (ifm->ifm_flags & IFF_LOOPBACK)  /* is a loopback net    */
 
173
      ii->info |= IFACE_INFO_LOOPBACK;
 
174
    if (ifm->ifm_flags & IFF_POINTOPOINT)       /* point to point link  */
 
175
      ii->info |= IFACE_INFO_P2P;
 
176
    if (ifm->ifm_flags & IFF_BROADCAST) /* support broadcast    */
 
177
      ii->info |= IFACE_INFO_BROADCAST;
 
178
    if (ifm->ifm_flags & IFF_MULTICAST) /* support multicast    */
 
179
      ii->info |= IFACE_INFO_MULTICAST;
 
180
    if (ifm->ifm_flags & IFF_PROMISC)   /* receive all packets  */
 
181
      ii->info |= IFACE_INFO_PROMISC;
 
182
    /*if (ifm->ifm_flags & IFF_SIMPLEX)*/       /* can't hear own packets */
 
183
    /*      ii->info |= IFACE_INFO_SIMPLEX;*/
 
184
 
 
185
    /* Information about physical interface
 
186
     *  type / physaddr / addrlen
 
187
     */
 
188
    ii->type = sdl->sdl_type; // ::TODO:: type conversion
 
189
    if (sdl->sdl_alen > 0) {
 
190
      ii->phys.size = sdl->sdl_alen;
 
191
      ii->phys.addr = malloc(ii->phys.size);
 
192
      if (ii->phys.addr == NULL) {
 
193
        errno = ENOMEM;
 
194
        goto failed;
 
195
      }
 
196
      memcpy(ii->phys.addr, LLADDR(sdl), ii->phys.size);
 
197
    }
 
198
 
 
199
    /* Retrieve addresses
 
200
     */
 
201
    ii->addrs = &hdlr->addr_list[addr_pos];
 
202
 
 
203
    next += ifm->ifm_msglen;
 
204
    while (next < lim) {
 
205
      struct sockaddr   *sa[RTAX_MAX];
 
206
      struct if_msghdr  *nextifm        = (struct if_msghdr *)next;
 
207
      struct ifa_msghdr *ifam           = (struct ifa_msghdr *)nextifm;
 
208
      char              *cp             = (char *)(ifam + 1);
 
209
 
 
210
      /* Check for end
 
211
       */
 
212
      if (nextifm->ifm_type != RTM_NEWADDR)
 
213
        break;
 
214
 
 
215
      /* Unpack address information
 
216
       */
 
217
      memset(sa, 0, sizeof(sa));
 
218
      for (i = 0; (i < RTAX_MAX) && (cp < lim); i++) {
 
219
        if ((ifam->ifam_addrs & (1 << i)) == 0)
 
220
          continue;
 
221
        sa[i] = SA(cp);
 
222
        cp += ROUNDUP(sa[i]->sa_len);
 
223
      }
 
224
 
 
225
      /* Basic information about interface
 
226
       */
 
227
      ia                = &hdlr->addr_list[addr_pos];
 
228
      ia->family        = -1;
 
229
      ia->ifi   = ii;
 
230
      ia->next  = &hdlr->addr_list[addr_pos+1];
 
231
 
 
232
      /* Process accroding to address family
 
233
       */
 
234
      if (sa[RTAX_IFA]) {
 
235
        ia->family = sa[RTAX_IFA]->sa_family;
 
236
        switch(ia->family) {
 
237
        case AF_INET:
 
238
          in4_cpy(&ia->af.inet.addr, IN4(sa[RTAX_IFA]));
 
239
          in4_cpy(&ia->af.inet.bcast,
 
240
                  sa[RTAX_BRD]?IN4(sa[RTAX_BRD]):IN4(sa[RTAX_IFA]));
 
241
          ia->af.inet.mask = sa[RTAX_NETMASK]
 
242
            ? prefixlen(IN4(sa[RTAX_NETMASK]),sizeof(struct in_addr))
 
243
            : 8 * sizeof(struct in_addr);
 
244
          break;
 
245
        case AF_INET6:
 
246
          in6_cpy(&ia->af.inet6.addr, IN6(sa[RTAX_IFA]));
 
247
          ia->af.inet6.prefixlen = sa[RTAX_NETMASK]
 
248
            ? prefixlen(IN6(sa[RTAX_NETMASK]),sizeof(struct in6_addr))
 
249
            : 8 * sizeof(struct in6_addr);
 
250
          break;
 
251
        default:
 
252
          /* Don't know how to process it, so ignore it
 
253
           */
 
254
          break;
 
255
        }
 
256
      }
 
257
 
 
258
      next += nextifm->ifm_msglen;
 
259
      acount++;
 
260
      addr_pos++;
 
261
    }
 
262
    ia->next = NULL;
 
263
    if (acount == 0)
 
264
      ii->addrs = NULL;
 
265
 
 
266
    if_pos++;
 
267
  }
 
268
  hdlr->if_list[hdlr->if_count-1].next = NULL;
 
269
 
 
270
  free(buf);
 
271
  return hdlr;
 
272
 
 
273
 failed:
 
274
  iface_destroy(hdlr);
 
275
  free(buf);
 
276
  return NULL;
 
277
}
 
278
 
 
279
#else
 
280
 
 
281
/* TODO: Using ioctl for getting interface addresses */
 
282
#ifdef LINUX
 
283
#define PATH_PROC_NET_IF_INET6 "/proc/net/if_inet6"
 
284
static int iface_getflags(struct iface_if *ii) {
 
285
  int sock;
 
286
  struct ifreq lifreq;
 
287
 
 
288
  strncpy(lifreq.ifr_name, ii->name,IFNAMSIZ);
 
289
  lifreq.ifr_addr.sa_family = AF_INET;
 
290
  if ((sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
 
291
    return -1;
 
292
  /* Interface flags */
 
293
  if (ioctl(sock, SIOCGIFFLAGS,&lifreq) < 0)
 
294
    return -1;
 
295
  if (lifreq.ifr_flags & IFF_UP)              /* interface is UP      */
 
296
    ii->info |= IFACE_INFO_UP;
 
297
  if (lifreq.ifr_flags & IFF_LOOPBACK)        /* is a loopback net    */
 
298
    ii->info |= IFACE_INFO_LOOPBACK;
 
299
  if (lifreq.ifr_flags & IFF_POINTOPOINT)     /* point to point link  */
 
300
    ii->info |= IFACE_INFO_P2P;
 
301
  if (lifreq.ifr_flags & IFF_BROADCAST)       /* support broadcast    */
 
302
    ii->info |= IFACE_INFO_BROADCAST;
 
303
  if (lifreq.ifr_flags & IFF_MULTICAST)       /* support multicast    */
 
304
    ii->info |= IFACE_INFO_MULTICAST;
 
305
  if (lifreq.ifr_flags & IFF_PROMISC) /* receive all packets  */
 
306
    ii->info |= IFACE_INFO_PROMISC;
 
307
  return 1;
 
308
}
 
309
 
 
310
/* **************************************************** */
 
311
 
 
312
struct iface_handler *iface_new(void) {
 
313
  char buf[1024];
 
314
  char straddr[33];
 
315
  char bufntop[67];
 
316
  char ifname[20];
 
317
  int ifindex, plen, scope, status;
 
318
  int found = 0;
 
319
  struct iface_handler * hdlr;
 
320
  FILE *fp;
 
321
  int n;
 
322
  struct iface_if *ii, *itf;
 
323
  struct iface_addr *ia, *it;
 
324
  struct in6_addr addr;
 
325
 
 
326
  /* Allocate memory for iface handler
 
327
   */
 
328
  if (! (hdlr = (struct iface_handler *)calloc(1,sizeof(struct iface_handler)))){
 
329
    errno = ENOMEM;
 
330
    goto failed;
 
331
  }
 
332
  fp = fopen(PATH_PROC_NET_IF_INET6,"r");
 
333
  if (fp == NULL)
 
334
    goto failed;
 
335
  hdlr->if_list = ii = NULL;
 
336
  hdlr->addr_list = ia = NULL;
 
337
  while (fgets(buf, 1024, fp) != NULL){
 
338
    n = sscanf(buf, "%32s %02x %02x %02x %02x %20s",
 
339
               straddr, &ifindex,&plen, &scope, &status, ifname);
 
340
    if (n != 6)
 
341
      continue;
 
342
    str2in6_addr(straddr, &addr);
 
343
    /* search existing interface */
 
344
    for (itf = hdlr->if_list;itf; itf= itf->next){
 
345
      if (strncmp(itf->name, ifname,IFNAMSIZ) == 0){
 
346
        /* update addresses*/
 
347
        for (it = itf->addrs;it->next != NULL ; it = it->next);
 
348
        ia = (struct iface_addr *) malloc(sizeof(struct iface_addr));
 
349
        ia->family = AF_INET6;
 
350
        ia->ifi = itf;
 
351
        in6_cpy(&ia->af.inet6.addr, &addr);
 
352
        ia->af.inet6.prefixlen = plen;
 
353
        ia->next = NULL;
 
354
        it->next = ia;
 
355
        found = 1;
 
356
      }
 
357
    }
 
358
    if (!found){
 
359
      /* New interface/ address */
 
360
      itf = (struct iface_if *)malloc(sizeof(struct iface_if));
 
361
      itf->next = NULL;
 
362
      memcpy(itf->name, ifname, IFNAMSIZ);
 
363
      itf->index = ifindex;
 
364
      iface_getflags(itf);
 
365
      it = itf->addrs =(struct iface_addr *) malloc(sizeof(struct iface_addr));
 
366
      it->family = AF_INET6;
 
367
      it->ifi = itf;
 
368
      in6_cpy(&it->af.inet6.addr, &addr);
 
369
      it->af.inet6.prefixlen = plen;
 
370
      it->next = NULL;
 
371
      if (ii == NULL){
 
372
        hdlr->if_list = itf;
 
373
        hdlr->addr_list = it;
 
374
      }else {
 
375
        ii->next = itf;
 
376
      }
 
377
      ii = itf;
 
378
      hdlr->if_count++;
 
379
 
 
380
    }
 
381
  }
 
382
  return hdlr;
 
383
 failed:
 
384
  iface_destroy(hdlr);
 
385
  return NULL;
 
386
 
 
387
}
 
388
#else
 
389
 
 
390
/* != LINUX */
 
391
struct iface_handler *iface_new(void) {
 
392
  return NULL;
 
393
}
 
394
#endif
 
395
#endif
 
396
 
 
397
/* ******************************************************* */
 
398
 
 
399
void iface_destroy(struct iface_handler *hdlr) {
 
400
  if (hdlr) {
 
401
    if (hdlr->addr_list)
 
402
      free(hdlr->addr_list);
 
403
    if (hdlr->if_list) {
 
404
#if defined(HAVE_IFLIST_SYSCTL) && defined(HAVE_SYSCTL)
 
405
      int i;
 
406
      for (i = 0 ; i < hdlr->if_count ; i++)
 
407
        if (hdlr->if_list[i].phys.addr)
 
408
          free(hdlr->if_list[i].phys.addr);
 
409
#endif
 
410
      free(hdlr->if_list);
 
411
    }
 
412
    free(hdlr);
 
413
  }
 
414
}
 
415
 
 
416
int iface_addrcount(struct iface_handler *hdlr) {
 
417
  return hdlr->addr_count;
 
418
}
 
419
 
 
420
 
 
421
int iface_ifcount(struct iface_handler *hdlr) {
 
422
  return hdlr->if_count;
 
423
}
 
424
 
 
425
 
 
426
struct iface_if *iface_getif_first(struct iface_handler *hdlr) {
 
427
  return hdlr->if_count ? &hdlr->if_list[0] : NULL;
 
428
}
 
429
 
 
430
 
 
431
struct iface_if *iface_getif_next(struct iface_if *ii) {
 
432
  return ii ? ii->next : NULL;
 
433
}
 
434
 
 
435
 
 
436
int iface_if_addrcount(struct iface_if *ii, int family) {
 
437
  struct iface_addr *ia;
 
438
  int count = 0;
 
439
 
 
440
  for (ia = ii->addrs ; ia ; ia = ia->next)
 
441
    if (!family || (ia->family == family))
 
442
      count++;
 
443
  return count;
 
444
}
 
445
 
 
446
 
 
447
 
 
448
struct iface_if *iface_getif_byindex(struct iface_handler *hdlr, int idx) {
 
449
  int i;
 
450
 
 
451
  for (i = 0 ; i < hdlr->if_count ; i++)
 
452
    if (hdlr->if_list[i].index == idx)
 
453
      return &hdlr->if_list[i];
 
454
  return NULL;
 
455
}
 
456
 
 
457
 
 
458
struct iface_if *iface_getif_byname(struct iface_handler *hdlr, char *name) {
 
459
  int i;
 
460
 
 
461
  for (i = 0 ; i < hdlr->if_count ; i++)
 
462
    if (! strcmp(hdlr->if_list[i].name, name))
 
463
      return &hdlr->if_list[i];
 
464
  return NULL;
 
465
}
 
466
 
 
467
 
 
468
char *iface_if_getname(struct iface_if *ii, char *name, int size) {
 
469
  if (name) {
 
470
    name[size-1] = '\0';
 
471
    strncpy(name, ii->name, size);
 
472
  } else {
 
473
    name = strdup(ii->name);
 
474
  }
 
475
  return name;
 
476
}
 
477
 
 
478
int iface_if_getindex(struct iface_if *ii) {
 
479
  return ii->index;
 
480
}
 
481
 
 
482
 
 
483
 
 
484
int iface_if_getinfo(struct iface_if *ii) {
 
485
  return ii->info;
 
486
}
 
487
 
 
488
 
 
489
int iface_if_gettype(struct iface_if *ii) {
 
490
  return ii->type;
 
491
}
 
492
 
 
493
 
 
494
 
 
495
int iface_if_getphys(struct iface_if *ii,int *type,char *addr,int *addrsize) {
 
496
  if (type)
 
497
    *type = ii->type;
 
498
  if (addr) {
 
499
    *addrsize = *addrsize < ii->phys.size ? *addrsize : ii->phys.size;
 
500
    if (ii->phys.addr)
 
501
      memcpy(addr, ii->phys.addr, *addrsize);
 
502
  }
 
503
  return ii->phys.size;
 
504
}
 
505
 
 
506
 
 
507
struct iface_addr *iface_getaddr_first(struct iface_if *ii, int family) {
 
508
  struct iface_addr     *ia;
 
509
 
 
510
  if (! (ia = ii->addrs))
 
511
    return NULL;
 
512
  if (family && (ia->family != family))
 
513
    return iface_getaddr_next(ia, family);
 
514
  return ia;
 
515
}
 
516
 
 
517
struct iface_addr *iface_getaddr_next(struct iface_addr *ia, int family) {
 
518
  if (ia)
 
519
    do {
 
520
      ia = ia->next;
 
521
    } while (ia && family && (ia->family != family));
 
522
  return ia;
 
523
}
 
524
 
 
525
 
 
526
int iface_addr_getfamily(struct iface_addr *ia) {
 
527
  return ia->family;
 
528
}
 
529
 
 
530
 
 
531
int iface_addr_ifindex(struct iface_addr *ia) {
 
532
  return ia->ifi->index;
 
533
}
 
534
 
 
535
 
 
536
void *iface_addr_getinfo(struct iface_addr *ia, void *infobuf) {
 
537
  switch(ia->family) {
 
538
  case AF_INET:
 
539
    memcpy(infobuf, &ia->af.inet,  sizeof(struct iface_addr_inet));
 
540
    return infobuf;
 
541
  case AF_INET6:
 
542
    memcpy(infobuf, &ia->af.inet6, sizeof(struct iface_addr_inet6));
 
543
    return infobuf;
 
544
  default:
 
545
    return NULL;
 
546
  }
 
547
}
 
548
 
 
549
/* *************************************************** */
 
550
 
 
551
int iface6(int *idx, int size) {
 
552
  struct iface_if       *ii;
 
553
  struct iface_handler  *ih;
 
554
  int                   count   = 0;
 
555
 
 
556
 
 
557
  ih = iface_new();
 
558
 
 
559
  if(ih == NULL)
 
560
    return -1;
 
561
 
 
562
  for (ii = iface_getif_first(ih) ; ii ; ii = iface_getif_next(ii))
 
563
    if ((iface_if_getinfo(ii) & (IFACE_INFO_UP | IFACE_INFO_LOOPBACK)) ==
 
564
        IFACE_INFO_UP)
 
565
      if (iface_getaddr_first(ii, AF_INET6)) {
 
566
        if (idx) {
 
567
          if (count == size)
 
568
            return count;
 
569
          *idx++ = iface_if_getindex(ii);
 
570
        }
 
571
        count++;
 
572
      }
 
573
 
 
574
  iface_destroy(ih);
 
575
  return count;
 
576
}
 
577
 
 
578
 
 
579
#if 0
 
580
// check for using only SIOCGIF* instead of sysctl, it seems more
 
581
// protable
 
582
 
 
583
 
 
584
#define ESTIMATED_LOCAL 20
 
585
 
 
586
 
 
587
/*@brief expand sockaddr's included in <code>ifam</code>
 
588
 *
 
589
 *@param ifam message containing information about interface
 
590
 *            addresses.
 
591
 *@param ai structure where addresses will be expanded.
 
592
 */
 
593
 
 
594
 
 
595
void iface_unpackaddr(struct ifa_msghdr *ifam, struct rt_addrinfo *ai){
 
596
  char *wp;
 
597
  int rtax;
 
598
 
 
599
  wp = (char *)(ifam + 1);
 
600
 
 
601
  ai->rti_addrs = ifam->ifam_addrs;
 
602
  for (rtax = 0; rtax < sizeof ai->rti_info / sizeof *ai->rti_info; rtax++)
 
603
    if (ifam->ifam_addrs & (1 << rtax)) {
 
604
      ai->rti_info[rtax] = (struct sockaddr *)wp;
 
605
      wp += ROUNDUP(ai->rti_info[rtax]->sa_len);
 
606
    } else
 
607
      ai->rti_info[rtax] = NULL;
 
608
}
 
609
 
 
610
 
 
611
/*@ find all IP interfaces addreses
 
612
 *
 
613
 *@param type  adresses family (AF_INET / AF_INET6)
 
614
 *@param size  number of addresses found
 
615
 *@param addr  buffer of list of adresses should be IPv4/IPv6
 
616
 */
 
617
 
 
618
int iface_getalladdr(int type, int *size, char **addr){
 
619
  int mib[6], n, s, alloced;
 
620
  size_t needed;
 
621
  char *buf, *end, *ptr;
 
622
  struct if_msghdr *ifm;
 
623
  struct ifa_msghdr *ifam;
 
624
  struct rt_addrinfo ai;
 
625
  struct ifreq ifr;
 
626
  struct sockaddr_dl *dl;
 
627
  struct sockaddr_in6 *sin;
 
628
  int num_local = -1;
 
629
  struct in6_addr *saddr;
 
630
 
 
631
  mib[0] = CTL_NET;
 
632
  mib[1] = PF_ROUTE;
 
633
  mib[4] = NET_RT_IFLIST;
 
634
  mib[2] = mib[3] = mib[5] = 0;
 
635
 
 
636
  if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
 
637
    return -1;
 
638
  if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
 
639
    goto failed;
 
640
  if ((buf = (char *)malloc(needed)) == NULL)
 
641
    goto failed;
 
642
  if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
 
643
    goto failed;
 
644
  num_local = 0;
 
645
  alloced = 0;
 
646
  end = buf + needed;
 
647
 
 
648
  for (ptr = buf; ptr < end; ptr += ifm->ifm_msglen) {
 
649
    ifm = (struct if_msghdr *)ptr;
 
650
    dl = (struct sockaddr_dl *)(ifm + 1);
 
651
    if (ifm->ifm_index != dl->sdl_index || dl->sdl_nlen == 0)
 
652
      /* Skip over remaining ifa_msghdrs */
 
653
      continue;
 
654
    n = dl->sdl_nlen > sizeof(ifr.ifr_name) ?
 
655
      sizeof(ifr.ifr_name) : dl->sdl_nlen;
 
656
    strncpy(ifr.ifr_name, dl->sdl_data, n);
 
657
    if (n < sizeof (ifr.ifr_name))
 
658
      ifr.ifr_name[n] = '\0';
 
659
    if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
 
660
      return -1;
 
661
    else if (ifr.ifr_flags & IFF_UP) {
 
662
      ifam = (struct ifa_msghdr *)(ptr + ifm->ifm_msglen);
 
663
      while ((char *)ifam < end && ifam->ifam_type == RTM_NEWADDR) {
 
664
        iface_unpackaddr(ifam, &ai);
 
665
        switch (type){
 
666
        case AF_INET:
 
667
          if (ai.rti_info[RTAX_IFA] != NULL &&
 
668
              ai.rti_info[RTAX_IFA]->sa_family == AF_INET) {
 
669
            if (alloced < num_local + 1) {
 
670
              alloced += ESTIMATED_LOCAL;
 
671
              saddr = (struct in_addr *)realloc(saddr, alloced * sizeof(struct in_addr));
 
672
              if (saddr == NULL) {
 
673
                num_local = 0;
 
674
                goto failed;
 
675
                break;
 
676
              }
 
677
            }
 
678
            memcpy((struct in_addr *)&saddr[num_local++],
 
679
                   &(((struct sockaddr_in *)ai.rti_info[RTAX_IFA])->sin_addr),
 
680
                   sizeof(struct in_addr));
 
681
          }
 
682
          break;
 
683
        case AF_INET6:
 
684
          if (ai.rti_info[RTAX_IFA] != NULL &&
 
685
              ai.rti_info[RTAX_IFA]->sa_family == AF_INET6) {
 
686
            sin = (struct sockaddr_in6 *)ai.rti_info[RTAX_IFA];
 
687
            if (!IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) &&
 
688
                !IN6_IS_ADDR_LOOPBACK(&sin->sin6_addr)){
 
689
              if (alloced < num_local + 1) {
 
690
                alloced += ESTIMATED_LOCAL;
 
691
                saddr = (struct in6_addr *)realloc(saddr, alloced * sizeof saddr[0]);
 
692
                if (saddr == NULL) {
 
693
                  num_local = 0;
 
694
                  goto failed;
 
695
                  break;
 
696
                }
 
697
              }
 
698
            }
 
699
            memcpy(&saddr[num_local++],&sin->sin6_addr, sizeof(struct in6_addr));
 
700
          }
 
701
          break;
 
702
        default:
 
703
          goto failed;
 
704
        }
 
705
        ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
 
706
      }
 
707
    }
 
708
  }
 
709
  free(buf);
 
710
  close(s);
 
711
  *size = num_local;
 
712
  *addr = (char *)saddr;
 
713
  return 1;
 
714
 failed:
 
715
  free(buf);
 
716
  close(s);
 
717
  *size = num_local;
 
718
  *addr = NULL;
 
719
  return -1;
 
720
}
 
721
 
 
722
#endif
 
723
 
 
724
#endif /* INET6 */