forked from skx/sysadmin-util
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ipaddr.c
144 lines (126 loc) · 3.47 KB
/
ipaddr.c
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/**
* ipaddr - Show the IP addresses associated with given devices.
*
* Usage:
* ipaddr [options]
*
* Options:
*
* --all Show all families.
* --ipv4 Show IPv4 addresses.
* --ipv6 Show IPv6 addresses.
* --device Show only the given device.
*
* Examples:
*
* $ ipaddr -d eth0 -4
* eth0 192.168.0.3
*
* $ ipaddr -a
* lo 127.0.0.1
* eth0 192.168.0.3
* lo ::1
* eth0 fe80::62a4:4cff:fe2d:fab9
* teredo 2001:0:53ba:64c:301f:13f3:4fe4:3a0b
* teredo fe80::ffff:ffff:ffff
*
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <getopt.h>
int main (int argc, char * argv[])
{
int c;
/**
* Flags.
*/
char *dev = NULL;
int show_ipv4 = 0;
int show_ipv6 = 0;
while (1)
{
static struct option long_options[] =
{
{"all", no_argument, 0, 'a'},
{"device", required_argument, 0, 'd'},
{"ipv4", no_argument, 0, '4'},
{"ipv6", no_argument, 0, '6'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long(argc, argv, "ad:46", long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case '4':
show_ipv4 = 1;
break;
case '6':
show_ipv6 = 1;
break;
case 'a':
show_ipv4 = 1;
show_ipv6 = 1;
break;
case 'd':
dev = strdup( optarg );
break;
case '?':
/* getopt_long already printed an error message. */
exit(1);
break;
default:
fprintf( stderr, "Unknown argument" );
exit (1);
}
}
struct ifaddrs * ifAddrStruct=NULL;
struct ifaddrs * ifa=NULL;
void * tmpAddrPtr=NULL;
getifaddrs(&ifAddrStruct);
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next)
{
/**
* If we have a non-null entry.
*/
if ( ifa && ifa->ifa_addr )
{
/**
* And it is IPv4 and we're showing IPv4 ..
*/
if (ifa ->ifa_addr->sa_family==AF_INET && show_ipv4 )
{
tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
char addressBuffer[INET_ADDRSTRLEN];
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
if ( ( dev == NULL ) ||
( strcmp( dev, ifa->ifa_name ) == 0 ) )
printf("%s %s\n", ifa->ifa_name, addressBuffer);
}
else if (ifa->ifa_addr->sa_family==AF_INET6 && show_ipv6 )
{
/**
* IPv6 address, and we're showing them.
*/
tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
char addressBuffer[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
if ( ( dev == NULL ) ||
( strcmp( dev, ifa->ifa_name ) == 0 ) )
printf("%s %s\n", ifa->ifa_name, addressBuffer);
}
}
}
if (ifAddrStruct!=NULL)
freeifaddrs(ifAddrStruct);
return 0;
}