summaryrefslogtreecommitdiffstats
path: root/debian/patches/61_whoips.patch
blob: 382ba4d05aad3c407f0ca189ba17b18d5561d1d0 (plain)
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
Author: 
Description: 
Index: coreutils-8.24/src/who.c
===================================================================
--- coreutils-8.24.orig/src/who.c
+++ coreutils-8.24/src/who.c
@@ -28,6 +28,8 @@
 #include <assert.h>
 
 #include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
 #include "system.h"
 
 #include "c-ctype.h"
@@ -101,6 +103,9 @@ char *ttyname (int);
 /* If true, attempt to canonicalize hostnames via a DNS lookup. */
 static bool do_lookup;
 
+/* If true, display ips instead of hostnames */
+static bool do_ips;
+
 /* If true, display only a list of usernames and count of
    the users logged on.
    Ignored for 'who am i'.  */
@@ -156,7 +161,8 @@ static int time_format_width;
 /* for long options with no corresponding short option, use enum */
 enum
 {
-  LOOKUP_OPTION = CHAR_MAX + 1
+  LOOKUP_OPTION = CHAR_MAX + 1,
+  IPS_OPTION = CHAR_MAX + 2
 };
 
 static struct option const longopts[] =
@@ -166,6 +172,7 @@ static struct option const longopts[] =
   {"count", no_argument, NULL, 'q'},
   {"dead", no_argument, NULL, 'd'},
   {"heading", no_argument, NULL, 'H'},
+  {"ips", no_argument, NULL, IPS_OPTION},
   {"login", no_argument, NULL, 'l'},
   {"lookup", no_argument, NULL, LOOKUP_OPTION},
   {"message", no_argument, NULL, 'T'},
@@ -428,6 +435,63 @@ print_user (const STRUCT_UTMP *utmp_ent,
     }
 #endif
 
+  /* Needs configure check for ut_addr_v6, etc */
+  if (do_ips &&
+      memcmp(utmp_ent->ut_addr_v6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
+  {
+        /* Following code is from sysvinit-2.87dsf
+           (GPL Copyright 1991-2004 Miquel van Smoorenburg) */
+        struct sockaddr_in      sin;
+        struct sockaddr_in6     sin6;
+        struct sockaddr         *sa;
+        int                     salen, flags;
+        unsigned int            azero=0;
+	unsigned int		glblunicast=0, linklocal=0, localunicast=0;
+        int                     mapped = 0;
+        int			*a = utmp_ent->ut_addr_v6;
+
+        hoststr = xrealloc(hoststr, 256);
+
+        flags = do_lookup ? 0 : NI_NUMERICHOST;
+
+        /*
+         *      IPv4 or IPv6 ? We use 2 heuristics:
+         *      1. Current IPv6 range uses 2000-3fff or fc00-fdff or fec0-feff. 
+         *         Outside of that is illegal and must be IPv4.
+         *      2. If last 3 bytes are 0, must be IPv4
+         *      3. If IPv6 in IPv4, handle as IPv4
+         *
+         *      Ugly.
+         */
+        if (a[0] == 0 && a[1] == 0 && a[2] == htonl (0xffff))
+                mapped = 1;
+
+	azero = ntohl((unsigned int)a[0]) >> 16;
+	glblunicast = (azero >= 0x2000 && azero <= 0x3fff) ? 1 : 0;
+	localunicast = (azero >= 0xfc00 && azero <= 0xfdff) ? 1 : 0;
+	linklocal = (azero >= 0xfec0 && azero <= 0xfeff) ? 1 : 0;
+
+        if (!(glblunicast || linklocal || localunicast) || mapped ||
+            (a[1] == 0 && a[2] == 0 && a[3] == 0)) {
+                /* IPv4 */
+                sin.sin_family = AF_INET;
+                sin.sin_port = 0;
+                sin.sin_addr.s_addr = mapped ? a[3] : a[0];
+                sa = (struct sockaddr *)&sin;
+                salen = sizeof(sin);
+        } else {
+                /* IPv6 */
+                memset(&sin6, 0, sizeof(sin6));
+                sin6.sin6_family = AF_INET6;
+                sin6.sin6_port = 0;
+                memcpy(sin6.sin6_addr.s6_addr, a, 16);
+                sa = (struct sockaddr *)&sin6;
+                salen = sizeof(sin6);
+        }
+
+	getnameinfo(sa, salen, hoststr, 256, NULL, 0, flags);
+  }
+
   print_line (sizeof UT_USER (utmp_ent), UT_USER (utmp_ent), mesg,
               sizeof utmp_ent->ut_line, utmp_ent->ut_line,
               time_string (utmp_ent), idlestr, pidstr,
@@ -649,6 +713,11 @@ Print information about users who are cu
   -H, --heading     print line of column headings\n\
 "), stdout);
       fputs (_("\
+      --ips         print ips instead of hostnames. with --lookup,\n\
+                    canonicalizes based on stored IP, if available,\n\
+                    rather than stored hostname\n\
+"), stdout);
+      fputs (_("\
   -l, --login       print system login processes\n\
 "), stdout);
       fputs (_("\
@@ -778,6 +847,10 @@ main (int argc, char **argv)
           do_lookup = true;
           break;
 
+        case IPS_OPTION:
+          do_ips = true;
+          break;
+
         case_GETOPT_HELP_CHAR;
 
         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);