]> git.proxmox.com Git - mirror_iproute2.git/blob - Patches/pidentd-3.0.12.dif
6e54e9362f6185797174415f8946e1fe4262f307
[mirror_iproute2.git] / Patches / pidentd-3.0.12.dif
1 diff -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 }