summaryrefslogtreecommitdiff
path: root/src/minidentd/mgetuid-linux.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/minidentd/mgetuid-linux.c')
-rw-r--r--src/minidentd/mgetuid-linux.c169
1 files changed, 169 insertions, 0 deletions
diff --git a/src/minidentd/mgetuid-linux.c b/src/minidentd/mgetuid-linux.c
new file mode 100644
index 0000000..442f642
--- /dev/null
+++ b/src/minidentd/mgetuid-linux.c
@@ -0,0 +1,169 @@
+/* ISC license. */
+
+#include <skalibs/uint16.h>
+#include <skalibs/uint32.h>
+#include <skalibs/uint.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/fmtscan.h>
+#include <skalibs/buffer.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/ip46.h>
+#include <skalibs/skamisc.h>
+#include "mgetuid.h"
+
+#ifdef DEBUG
+#include <skalibs/strerr2.h>
+#define bug(a) do { strerr_warn4x("bug parsing ", a, "remaining: ", cur) ; return 0 ; } while (0)
+#else
+#define bug(a) return 0
+#endif
+
+#define LINESIZE 256
+
+static int skipspace (char **s)
+{
+ while (**s && ((**s == ' ') || (**s == '\t')))
+ (*s)++ ;
+ return (int)**s ;
+}
+
+static int parseline (char *s, unsigned int len, unsigned int *u, char *la, uint16 *lp, char *ra, uint16 *rp, int is6)
+{
+ char *cur = s ;
+ unsigned int pos ;
+ uint32 junk ;
+ register unsigned int iplen = is6 ? 16 : 4 ;
+
+ if (!skipspace(&cur)) bug("initial whitespace") ;
+ pos = uint32_scan(cur, &junk) ; /* sl */
+ if (!pos || (cur-s+1+pos) > len) bug("sl") ;
+ cur += pos ;
+ if ((*cur++) != ':') bug("sl:") ;
+ if (!skipspace(&cur)) bug("sl: SPACE") ;
+
+ if ((cur - s + 1 + iplen) > len) bug("local_address") ;
+ pos = ucharn_scan(cur, la, iplen) ; /* local_address */
+ if (!pos) bug("local_address") ;
+ cur += pos ;
+ if ((*cur++) != ':') bug("local_address:") ;
+
+ pos = uint16_xscan(cur, lp) ; /* :port */
+ if (!pos || (cur-s+pos) > len) bug("local_port") ;
+ cur += pos ;
+ if (!skipspace(&cur)) bug("local_port SPACE") ;
+
+ if ((cur - s + 1 + iplen) > len) bug("remote_address") ;
+ pos = ucharn_scan(cur, ra, iplen) ; /* remote_address */
+ if (!pos) bug("remote_address") ;
+ cur += pos ;
+ if ((*cur++) != ':') bug("remote_address:") ;
+
+ pos = uint16_xscan(cur, rp) ; /* :port */
+ if (!pos || (cur-s+pos) > len) bug("remote_port") ;
+ cur += pos ;
+ if (!skipspace(&cur)) bug("remote_port SPACE");
+
+ pos = uint32_xscan(cur, &junk) ; /* st */
+ if (!pos || (cur-s+pos) > len) bug("st") ;
+ cur += pos ;
+ if (!skipspace(&cur)) bug("st SPACE") ;
+ pos = uint32_xscan(cur, &junk) ; /* tx_queue */
+ if (!pos || (cur-s+1+pos) > len) bug("tx_queue") ;
+ cur += pos ;
+ if ((*cur++) != ':') bug("tx_queue:") ;
+ pos = uint32_xscan(cur, &junk) ; /* rx_queue */
+ if (!pos || (cur-s+pos) > len) bug("rx_queue") ;
+ cur += pos ;
+ if (!skipspace(&cur)) bug("rx_queue SPACE") ;
+ pos = uint32_xscan(cur, &junk) ; /* tr */
+ if (!pos || (cur-s+1+pos) > len) bug("tr") ;
+ cur += pos ;
+ if ((*cur++) != ':') bug("tr:") ;
+ pos = uint32_xscan(cur, &junk) ; /* tm->when */
+ if (!pos || (cur-s+pos) > len) bug("tm->when") ;
+ cur += pos ;
+ if (!skipspace(&cur)) bug("tm->when SPACE") ;
+ pos = uint32_xscan(cur, &junk) ; /* retrnsmt */
+ if (!pos || (cur-s+pos) > len) bug("retrnsmt") ;
+ cur += pos ;
+
+ if (!skipspace(&cur)) bug("retrnsmt SPACE") ;
+ pos = uint_scan(cur, u) ; /* uid */
+ if (!pos || (cur-s+1+pos) > len) bug("uid") ;
+
+ return 1 ;
+}
+
+#ifdef DEBUG
+
+static void debuglog (uint16 a, uint16 b, unsigned int c, char const *d, char const *e, int is6)
+{
+ char sa[UINT16_FMT] ;
+ char sb[UINT16_FMT] ;
+ char sc[UINT_FMT] ;
+ char sd[IP46_FMT] ;
+ char se[IP46_FMT] ;
+
+ sa[uint16_fmt(sa, a)] = 0 ;
+ sb[uint16_fmt(sb, b)] = 0 ;
+ sc[uint_fmt(sc, c)] = 0 ;
+ sd[is6 ? ip6_fmt(sd, d) : ip4_fmt(sd, d)] = 0 ;
+ se[is6 ? ip6_fmt(se, e) : ip4_fmt(se, e)] = 0 ;
+
+ buffer_puts(buffer_2, sd) ;
+ buffer_puts(buffer_2, ":") ;
+ buffer_puts(buffer_2, sa) ;
+ buffer_puts(buffer_2, " , ") ;
+ buffer_puts(buffer_2, se) ;
+ buffer_puts(buffer_2, ":") ;
+ buffer_puts(buffer_2, sb) ;
+ buffer_puts(buffer_2, " -> ") ;
+ buffer_puts(buffer_2, sc) ;
+ buffer_putsflush(buffer_2, "\n") ;
+}
+
+#endif
+
+int mgetuid (ip46_t const *localaddr, uint16 localport, ip46_t const *remoteaddr, uint16 remoteport)
+{
+ int r ;
+ int u = -2 ;
+ stralloc line = STRALLOC_ZERO ;
+ buffer b ;
+ char y[BUFFER_INSIZE] ;
+ register int is6 = ip46_is6(localaddr) ;
+ int fd = open_readb(is6 ? "/proc/net/tcp6" : "/proc/net/tcp") ;
+ if (fd == -1) return -2 ;
+ buffer_init(&b, &buffer_read, fd, y, BUFFER_INSIZE_SMALL) ;
+ if (skagetln(&b, &line, '\n') < 1) goto err ;
+#ifdef DEBUG
+ line.s[line.len-1] = 0 ;
+ debuglog(localport, remoteport, 65535, localaddr->ip, remoteaddr->ip, is6) ;
+#endif
+ for (;;)
+ {
+ char la[16] ;
+ char ra[16] ;
+ unsigned int nu ;
+ uint16 lp, rp ;
+ line.len = 0 ;
+ r = skagetln(&b, &line, '\n') ;
+ if (r <= 0) { u = -1 ; break ; }
+ line.s[line.len-1] = 0 ;
+ if (!parseline(line.s, line.len, &nu, la, &lp, ra, &rp, is6)) break ;
+#ifdef DEBUG
+ debuglog(lp, rp, nu, la, ra, is6) ;
+#endif
+ if ((lp == localport) && (rp == remoteport)
+ && !byte_diff(la, is6 ? 16 : 4, localaddr->ip)
+ && !byte_diff(ra, is6 ? 16 : 4, remoteaddr->ip))
+ {
+ u = nu ; break ;
+ }
+ }
+ stralloc_free(&line) ;
+ err:
+ fd_close(fd) ;
+ return u ;
+}