File: localip.c

package info (click to toggle)
darkstat 3.0.708-2
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 708 kB
  • ctags: 592
  • sloc: ansic: 5,326; sh: 322; makefile: 131
file content (84 lines) | stat: -rw-r--r-- 2,139 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/* darkstat 3
 * copyright (c) 2001-2008 Emil Mikulic.
 *
 * localip.c: determine local IP of our capture interface
 *
 * You may use, modify and redistribute this file under the terms of the
 * GNU General Public License version 2. (see COPYING.GPL)
 */

#include "darkstat.h"
#include "conv.h" /* for strlcpy */
#include "decode.h" /* for ip_to_str */
#include "err.h"
#include "localip.h"

#ifdef HAVE_SYS_SOCKIO_H
# include <sys/sockio.h> /* for SIOCGIFADDR, especially on Solaris */
#endif
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>

static const char *iface = NULL;
in_addr_t localip = 0;
static in_addr_t last_localip = 0;

void
localip_init(const char *interface)
{
   iface = interface;
   localip_update();
}

void
localip_update(void)
{
   int tmp = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
   struct ifreq ifr;
   struct sockaddr sa;

   if (iface == NULL) {
      /* reading from capfile */
      localip = 0;
      return;
   }

   strlcpy(ifr.ifr_name, iface, IFNAMSIZ);
   ifr.ifr_addr.sa_family = AF_INET;
   if (ioctl(tmp, SIOCGIFADDR, &ifr) == -1) {
      if (errno == EADDRNOTAVAIL) {
         /* lost IP, e.g. ifconfig eth0 delete, don't die */
         localip = 0;
         close(tmp);
         return;
      } else
         err(1, "can't get own IP address on interface \"%s\"", iface);
   }
   close(tmp);
   sa = ifr.ifr_addr;

   /* struct sockaddr {
    *      sa_family_t     sa_family;      * address family, AF_xxx
    *      char            sa_data[14];    * 14 bytes of protocol address
    *
    * struct sockaddr_in {
    *      sa_family_t           sin_family;     * Address family
    *      unsigned short int    sin_port;       * Port number
    *      struct in_addr        sin_addr;       * Internet address
    *
    * struct in_addr {
    *      __u32   s_addr;
    */

   localip = ((struct sockaddr_in*)&sa)->sin_addr.s_addr;
   if (last_localip != localip) {
      verbosef("local_ip update(%s) = %s", iface, ip_to_str(localip));
      last_localip = localip;
   }
}

/* vim:set ts=3 sw=3 tw=78 expandtab: */