Fix netstat -- don't print all v4 addresses as v4-mapped-in-v6.
[oss-qm-packages.git] / lib / masq_info.c
blob45ca6896a04a25c639bda91ab4f75208b8621622
1 /*
2 * lib/masq_info.c This file contains a the functio masq_info
3 * to print a table of current masquerade connections.
5 * NET-LIB A collection of functions used from the base set of the
6 * NET-3 Networking Distribution for the LINUX operating
7 * system. (net-tools, net-drivers)
9 * Version: $Id: masq_info.c,v 1.7 2000/10/08 01:00:44 ecki Exp $
11 * Author: Bernd 'eckes' Eckenfels <net-tools@lina.inka.de>
12 * Copyright 1999 Bernd Eckenfels, Germany
14 * Modifications:
16 *960217 {0.01} Bernd Eckenfels: creatin from the code of
17 * Jos Vos' ipfwadm 2.0beta1
18 *950218 {0.02} Bernd Eckenfels: <linux/if.h> added
20 *980405 {0.03} Arnaldo Carvalho: i18n CATGETS -> gettext
22 * This program is free software; you can redistribute it
23 * and/or modify it under the terms of the GNU General
24 * Public License as published by the Free Software
25 * Foundation; either version 2 of the License, or (at
26 * your option) any later version.
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32 #include <errno.h>
33 #include <stdio.h>
34 #include <malloc.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include "net-support.h"
38 #include "pathnames.h"
39 #include "version.h"
40 #include "config.h"
41 #include "intl.h"
42 #include "net-features.h"
44 #if HAVE_FW_MASQUERADE
46 struct masq {
47 unsigned long expires; /* Expiration timer */
48 char *proto; /* Which protocol are we talking? */
49 struct sockaddr_in src, dst; /* Source and destination IP addresses */
50 unsigned short sport, dport; /* Source and destination ports */
51 unsigned short mport; /* Masqueraded port */
52 unsigned long initseq; /* Add delta from this seq. on */
53 short delta; /* Delta in sequence numbers */
54 short pdelta; /* Delta in sequence numbers before last */
57 static struct aftype *ap; /* current address family */
58 static int has_pdelta;
60 static void print_masq(struct masq *ms, int numeric_host, int numeric_port,
61 int ext)
63 unsigned long minutes, seconds, sec100s;
65 printf("%-4s", ms->proto);
67 sec100s = ms->expires % 100L;
68 seconds = (ms->expires / 100L) % 60;
69 minutes = ms->expires / 6000L;
71 printf("%3ld:%02ld.%02ld ", minutes, seconds, sec100s);
73 if (ext > 1) {
74 if (has_pdelta)
75 printf("%10lu %5hd %5hd ", ms->initseq,
76 ms->delta, ms->pdelta);
77 else
78 printf("%10lu %5hd - ", ms->initseq,
79 ms->delta);
81 printf("%-20s ", ap->sprint((struct sockaddr *) &(ms->src), numeric_host));
82 printf("%-20s ", ap->sprint((struct sockaddr *) &(ms->dst), numeric_host));
84 printf("%s -> ", get_sname(ms->sport, ms->proto, numeric_port));
85 printf("%s", get_sname(ms->dport, ms->proto, numeric_port));
86 printf(" (%s)\n", get_sname(ms->mport, ms->proto, numeric_port));
90 static int read_masqinfo(FILE * f, struct masq *mslist, int nmslist)
92 int n, nread = 0;
93 struct masq *ms;
94 char buf[256];
96 for (nread = 0; nread < nmslist; nread++) {
97 ms = &mslist[nread];
98 if (has_pdelta) {
99 if ((n = fscanf(f, " %s %lX:%hX %lX:%hX %hX %lX %hd %hd %lu",
100 buf,
101 (unsigned long *) &ms->src.sin_addr.s_addr, &ms->sport,
102 (unsigned long *) &ms->dst.sin_addr.s_addr, &ms->dport,
103 &ms->mport, &ms->initseq, &ms->delta,
104 &ms->pdelta, &ms->expires)) == -1)
105 return nread;
106 } else {
107 if ((n = fscanf(f, " %s %lX:%hX %lX:%hX %hX %lX %hd %lu",
108 buf,
109 (unsigned long *) &ms->src.sin_addr.s_addr, &ms->sport,
110 (unsigned long *) &ms->dst.sin_addr.s_addr, &ms->dport,
111 &ms->mport, &ms->initseq, &ms->delta,
112 &ms->expires)) == -1)
113 return nread;
115 if ((has_pdelta && (n != 10)) || (!has_pdelta && (n != 9))) {
116 EINTERN("masq_info.c", "ip_masquerade format error");
117 return (-1);
119 ms->src.sin_family = AF_INET;
120 ms->dst.sin_family = AF_INET;
122 if (strcmp("TCP", buf) == 0)
123 ms->proto = "tcp";
124 else if (strcmp("UDP", buf) == 0)
125 ms->proto = "udp";
126 else if (strcmp("ICMP", buf) == 0)
127 ms->proto = "icmp";
128 else if (strcmp("GRE", buf) == 0)
129 ms->proto = "gre";
130 else if (strcmp("ESP", buf) == 0)
131 ms->proto = "esp";
132 else {
133 EINTERN("masq_info.c", "ip_masquerade unknown type");
134 return (-1);
137 /* we always keep these addresses in network byte order */
138 ms->src.sin_addr.s_addr = htonl(ms->src.sin_addr.s_addr);
139 ms->dst.sin_addr.s_addr = htonl(ms->dst.sin_addr.s_addr);
140 ms->sport = htons(ms->sport);
141 ms->dport = htons(ms->dport);
142 ms->mport = htons(ms->mport);
144 return nread;
148 int ip_masq_info(int numeric_host, int numeric_port, int ext)
150 FILE *f;
151 int i;
152 char buf[256];
153 struct masq *mslist;
154 int ntotal = 0, nread;
156 if (!(f = fopen(_PATH_PROCNET_IP_MASQ, "r"))) {
157 if (errno != ENOENT) {
158 perror(_PATH_PROCNET_IP_MASQ);
159 return (-1);
161 ESYSNOT("netstat", "ip_masquerade");
162 return (1);
164 if ((ap = get_aftype("inet")) == NULL) {
165 ENOSUPP("masq_info", "AF INET");
166 fclose(f);
167 return (-1);
169 fgets(buf, sizeof(buf), f);
170 has_pdelta = strstr(buf, "PDelta") ? 1 : 0;
172 mslist = (struct masq *) malloc(16 * sizeof(struct masq));
173 if (!mslist) {
174 EINTERN("masq_info", "malloc() failed");
175 fclose(f);
176 return (-1);
178 while ((nread = read_masqinfo(f, &(mslist[ntotal]), 16)) == 16) {
179 ntotal += nread;
180 mslist = (struct masq *) realloc(mslist,
181 (ntotal + 16) * sizeof(struct masq));
182 if (!mslist) {
183 EINTERN("masq_info", "realloc() failed");
184 fclose(f);
185 return (-1);
188 fclose(f);
190 if (nread < 0) {
191 if (mslist)
192 free(mslist);
193 return (-1);
195 ntotal += nread;
197 if (ntotal > 0) {
198 printf(_("IP masquerading entries\n"));
199 switch (ext) {
200 case 1:
201 printf(_("prot expire source destination ports\n"));
202 break;
203 default:
204 printf(_("prot expire initseq delta prevd source destination ports\n"));
205 break;
207 for (i = 0; i < ntotal; i++)
208 print_masq(&(mslist[i]), numeric_host, numeric_port, ext);
209 if (mslist)
210 free(mslist);
213 return 0;
215 #endif