]> git.proxmox.com Git - mirror_iproute2.git/blame - Patches/pidentd-3.0.12.dif
(Logical change 1.3)
[mirror_iproute2.git] / Patches / pidentd-3.0.12.dif
CommitLineData
aba5acdf
SH
1diff -ur ../pidentd-3.0.12-orig/src/k_linux.c ./src/k_linux.c
2--- ../pidentd-3.0.12-orig/src/k_linux.c Sat Jan 12 00:44:05 2002
3+++ ./src/k_linux.c Sat Nov 3 07:51:28 2001
4@@ -26,12 +26,65 @@
5
6 #include "pidentd.h"
7
8+#define NETLINK_TCPDIAG 4
9+#define TCPDIAG_GETSOCK 18
10+
11+#include <linux/uio.h>
12+#include <linux/netlink.h>
13+
14+/* Socket identity */
15+struct tcpdiag_sockid
16+{
17+ __u16 tcpdiag_sport;
18+ __u16 tcpdiag_dport;
19+ __u32 tcpdiag_src[4];
20+ __u32 tcpdiag_dst[4];
21+ __u32 tcpdiag_if;
22+ __u32 tcpdiag_cookie[2];
23+#define TCPDIAG_NOCOOKIE (~0U)
24+};
25+
26+/* Request structure */
27+
28+struct tcpdiagreq
29+{
30+ __u8 tcpdiag_family; /* Family of addresses. */
31+ __u8 tcpdiag_src_len;
32+ __u8 tcpdiag_dst_len;
33+ __u8 tcpdiag_ext; /* Query extended information */
34+
35+ struct tcpdiag_sockid id;
36+
37+ __u32 tcpdiag_states; /* States to dump */
38+ __u32 tcpdiag_dbs; /* Tables to dump (NI) */
39+};
40+
41+struct tcpdiagmsg
42+{
43+ __u8 tcpdiag_family;
44+ __u8 tcpdiag_state;
45+ __u8 tcpdiag_timer;
46+ __u8 tcpdiag_retrans;
47+
48+ struct tcpdiag_sockid id;
49+
50+ __u32 tcpdiag_expires;
51+ __u32 tcpdiag_rqueue;
52+ __u32 tcpdiag_wqueue;
53+ __u32 tcpdiag_uid;
54+ __u32 tcpdiag_inode;
55+};
56+
57+
58+int tcpdiag_fd = -1;
59+
60 /*
61 ** Make sure we are running on a supported OS version
62 */
63 int
64 ka_init(void)
65 {
66+ tcpdiag_fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_TCPDIAG);
67 return 0; /* We always succeed */
68 }
69
70@@ -56,6 +109,144 @@
71 }
72
73
74+
75+int k_lookup_tcpdiag(struct kernel *kp)
76+{
77+ struct sockaddr_nl nladdr;
78+ struct {
79+ struct nlmsghdr nlh;
80+ struct tcpdiagreq r;
81+ } req;
82+ struct msghdr msg;
83+ char buf[8192];
84+ struct iovec iov[1];
85+ struct tcpdiagmsg *r;
86+ static unsigned seqno = 123456;
87+
88+ memset(&nladdr, 0, sizeof(nladdr));
89+ nladdr.nl_family = AF_NETLINK;
90+
91+ req.nlh.nlmsg_len = sizeof(req);
92+ req.nlh.nlmsg_type = TCPDIAG_GETSOCK;
93+ req.nlh.nlmsg_flags = NLM_F_REQUEST;
94+ req.nlh.nlmsg_pid = 0;
95+ req.nlh.nlmsg_seq = ++seqno;
96+ memset(&req.r, 0, sizeof(req.r));
97+ req.r.tcpdiag_family = AF_INET;
98+ req.r.tcpdiag_states = ~0;
99+
100+ req.r.id.tcpdiag_dport = kp->remote.sin_port;
101+ req.r.id.tcpdiag_sport = kp->local.sin_port;
102+ req.r.id.tcpdiag_dst[0] = kp->remote.sin_addr.s_addr;
103+ req.r.id.tcpdiag_src[0] = kp->local.sin_addr.s_addr;
104+ req.r.id.tcpdiag_cookie[0] = TCPDIAG_NOCOOKIE;
105+ req.r.id.tcpdiag_cookie[1] = TCPDIAG_NOCOOKIE;
106+ kp->ruid = NO_UID;
107+
108+ iov[0] = (struct iovec){ &req, sizeof(req) };
109+
110+ msg = (struct msghdr) {
111+ (void*)&nladdr, sizeof(nladdr),
112+ iov, 1,
113+ NULL, 0,
114+ 0
115+ };
116+
117+ if (sendmsg(tcpdiag_fd, &msg, 0) < 0) {
118+ if (errno == ECONNREFUSED) {
119+ close(tcpdiag_fd);
120+ tcpdiag_fd = -1;
121+ return 0;
122+ }
123+ syslog(LOG_ERR, "system error on tcpdiag sendmsg: %m");
124+ return -1;
125+ }
126+
127+ iov[0] = (struct iovec){ buf, sizeof(buf) };
128+
129+ while (1) {
130+ int status;
131+ struct nlmsghdr *h;
132+
133+ msg = (struct msghdr) {
134+ (void*)&nladdr, sizeof(nladdr),
135+ iov, 1,
136+ NULL, 0,
137+ 0
138+ };
139+
140+ status = recvmsg(tcpdiag_fd, &msg, 0);
141+
142+ if (status < 0) {
143+ if (errno == EINTR || errno == EAGAIN)
144+ continue;
145+ return -1;
146+ }
147+ if (status == 0) {
148+ return -1;
149+ }
150+
151+ h = (struct nlmsghdr*)buf;
152+ while (NLMSG_OK(h, status)) {
153+ int err;
154+
155+ if (/*h->nlmsg_pid != rth->local.nl_pid ||*/
156+ h->nlmsg_seq != seqno)
157+ goto skip_it;
158+
159+ if (h->nlmsg_type == NLMSG_DONE)
160+ return -1;
161+ if (h->nlmsg_type == NLMSG_ERROR) {
162+ struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
163+ if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
164+ return -1;
165+ } else {
166+ errno = -err->error;
167+ if (errno == ECONNREFUSED) {
168+ close(tcpdiag_fd);
169+ tcpdiag_fd = -1;
170+ return 0;
171+ }
172+ if (errno != ENOENT)
173+ syslog(LOG_ERR, "tcpdiag answers: %m");
174+ }
175+ return -1;
176+ }
177+
178+ r = NLMSG_DATA(h);
179+
180+ /* Lookup _may_ return listening socket, if no
181+ * better matches are found. */
182+ if (r->id.tcpdiag_dport == kp->remote.sin_port &&
183+ r->id.tcpdiag_dst[0] == kp->remote.sin_addr.s_addr) {
184+ kp->ruid = r->tcpdiag_uid;
185+ if (!r->tcpdiag_inode && !r->tcpdiag_uid) {
186+ /* _NEVER_ return "root" for closed
187+ * sockets. Otherwise people think
188+ * that it is sysadmin who abuses their
189+ * poor ircd. :-) */
190+ syslog(LOG_NOTICE,
191+ "Req for stale socket(%d) %d from %x/%d",
192+ r->tcpdiag_state, ntohs(r->id.tcpdiag_sport),
193+ r->id.tcpdiag_dst[0], ntohs(r->id.tcpdiag_dport));
194+ return -1;
195+ }
196+ return 1;
197+ }
198+
199+ return -1;
200+
201+skip_it:
202+ h = NLMSG_NEXT(h, status);
203+ }
204+ if ((msg.msg_flags & MSG_TRUNC) || status) {
205+ syslog(LOG_ERR, "truncated tcp_diag message");
206+ return -1;
207+ }
208+ }
209+}
210+
211+
212 int
213 ka_lookup(void *vp, struct kernel *kp)
214 {
215@@ -64,16 +255,23 @@
216 long r_laddr, r_raddr, myladdr, myraddr;
217 int r_lport, r_rport, mylport, myrport;
218 int euid;
219-
220-
221+
222+ if (tcpdiag_fd >= 0) {
223+ int res;
224+ if ((res = k_lookup_tcpdiag(kp)) != 0)
225+ return res;
226+ syslog(LOG_ERR, "tcp_diag is not loaded, fallback to proc");
227+ }
228+
229+
230 r_rport = ntohs(kp->remote.sin_port);
231 r_lport = ntohs(kp->local.sin_port);
232 r_raddr = kp->remote.sin_addr.s_addr;
233 r_laddr = kp->local.sin_addr.s_addr;
234+ kp->ruid = NO_UID;
235
236 fp = (FILE *) vp;
237
238- kp->ruid = NO_UID;
239 rewind(fp);
240
241 /* eat header */
242@@ -82,13 +280,26 @@
243
244 while (fgets(buf, sizeof(buf)-1, fp) != NULL)
245 {
246- if (sscanf(buf, "%*d: %lx:%x %lx:%x %*x %*x:%*x %*x:%*x %*x %d %*d %*d",
247- &myladdr, &mylport, &myraddr, &myrport, &euid) == 5)
248+ int state, ino;
249+ if (sscanf(buf, "%*d: %x:%x %x:%x %x %*x:%*x %*x:%*x %*x %d %*d %u",
250+ &myladdr, &mylport, &myraddr, &myrport,
251+ &state, &euid, &ino) == 7)
252 {
253 if (myladdr == r_laddr && mylport == r_lport &&
254 myraddr == r_raddr && myrport == r_rport)
255 {
256 kp->euid = euid;
257+ if (ino == 0 && euid == 0)
258+ {
259+ /* _NEVER_ return "root" for closed
260+ * sockets. Otherwise people think
261+ * that it is sysadmin who abuses their
262+ * poor ircd. :-) */
263+ syslog(LOG_NOTICE,
264+ "Req for stale socket(%d) %d from %x/%d",
265+ state, r_rport, r_raddr, r_lport);
266+ return -1;
267+ }
268 return 1;
269 }
270 }