2 * Copyright (C) 1993-2001 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
6 #if defined(__sgi) && (IRIX > 602)
7 # include <sys/ptimers.h>
10 #if !defined(__SVR4) && !defined(__svr4__)
13 #include <sys/byteorder.h>
15 #include <sys/param.h>
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <netinet/in_systm.h>
20 #include <netinet/ip.h>
21 #include <netinet/tcp.h>
23 #if __FreeBSD_version >= 300000
24 # include <net/if_var.h>
33 #include <arpa/nameser.h>
34 #include <arpa/inet.h>
38 #include "ip_compat.h"
44 static const char sccsid
[] = "@(#)parse.c 1.44 6/5/96 (C) 1993-2000 Darren Reed";
45 static const char rcsid
[] = "@(#)$IPFilter: parse.c,v 2.8 1999/12/28 10:49:46 darrenr Exp $";
48 extern struct ipopt_names ionames
[], secclass
[];
54 char flagset
[] = "FSRPAUEC";
55 u_char flags
[] = { TH_FIN
, TH_SYN
, TH_RST
, TH_PUSH
, TH_ACK
, TH_URG
,
58 void fill6bits
__P((int, u_32_t
*));
59 int count6bits
__P((u_32_t
*));
61 static char thishost
[MAXHOSTNAMELEN
];
66 gethostname(thishost
, sizeof(thishost
));
67 thishost
[sizeof(thishost
) - 1] = '\0';
71 int genmask(msk
, mskp
)
81 if (index(msk
, '.') || index(msk
, 'x') || index(msk
, ':')) {
82 /* possibly of the form xxx.xxx.xxx.xxx
86 if (inet_pton(AF_INET6
, msk
, &addr
) != 1)
90 if (inet_aton(msk
, (struct in_addr
*)mskp
) == 0)
94 * set x most significant bits
96 bits
= (int)strtol(msk
, &endptr
, 0);
97 if ((*endptr
!= '\0') ||
98 ((bits
> 32) && !use_inet6
) || (bits
< 0) ||
99 ((bits
> 128) && use_inet6
))
102 fill6bits(bits
, mskp
);
107 *mskp
= htonl(0xffffffff << (32 - bits
));
115 void fill6bits(bits
, msk
)
121 for (i
= 0; bits
>= 32 && i
< 4 ; ++i
, bits
-= 32)
124 if (bits
> 0 && i
< 4)
125 msk
[i
++] = htonl(0xffffffff << (32 - bits
));
133 * returns -1 if neither "hostmask/num" or "hostmask mask addr" are
134 * found in the line segments, there is an error processing this information,
135 * or there is an error processing ports information.
137 int hostmask(seg
, sa
, msk
, pp
, cp
, tp
, linenum
)
144 struct in_addr maskaddr
;
148 * is it possibly hostname/num ?
150 if ((s
= index(**seg
, '/')) ||
151 ((s
= index(**seg
, ':')) && !index(s
+ 1, ':'))) {
153 if (genmask(s
, msk
) == -1) {
154 fprintf(stderr
, "%d: bad mask (%s)\n", linenum
, s
);
157 if (hostnum(sa
, **seg
, linenum
) == -1) {
158 fprintf(stderr
, "%d: bad host (%s)\n", linenum
, **seg
);
163 return ports(seg
, pp
, cp
, tp
, linenum
);
167 * look for extra segments if "mask" found in right spot
169 if (*(*seg
+1) && *(*seg
+2) && !strcasecmp(*(*seg
+1), "mask")) {
170 if (hostnum(sa
, **seg
, linenum
) == -1) {
171 fprintf(stderr
, "%d: bad host (%s)\n", linenum
, **seg
);
176 if (inet_aton(**seg
, &maskaddr
) == 0) {
177 fprintf(stderr
, "%d: bad mask (%s)\n", linenum
, **seg
);
180 *msk
= maskaddr
.s_addr
;
183 return ports(seg
, pp
, cp
, tp
, linenum
);
187 if (hostnum(sa
, **seg
, linenum
) == -1) {
188 fprintf(stderr
, "%d: bad host (%s)\n", linenum
, **seg
);
194 if (sa
[0] || sa
[1] || sa
[2] || sa
[3])
196 msk
[0] = msk
[1] = msk
[2] = msk
[3] = k
;
199 *msk
= *sa
? 0xffffffff : 0;
200 return ports(seg
, pp
, cp
, tp
, linenum
);
202 fprintf(stderr
, "%d: bad host (%s)\n", linenum
, **seg
);
207 * returns an ip address as a long var as a result of either a DNS lookup or
208 * straight inet_addr() call
210 int hostnum(ipa
, host
, linenum
)
219 if (!strcasecmp("any", host
))
223 if (inet_pton(AF_INET6
, host
, ipa
) == 1)
229 if (isdigit(*host
) && inet_aton(host
, &ip
)) {
234 if (!strcasecmp("<thishost>", host
))
237 if (!(hp
= gethostbyname(host
))) {
238 if (!(np
= getnetbyname(host
))) {
239 fprintf(stderr
, "%d: can't resolve hostname: %s\n",
243 *ipa
= htonl(np
->n_net
);
246 *ipa
= *(u_32_t
*)hp
->h_addr
;
252 * check for possible presence of the port fields in the line
254 int ports(seg
, pp
, cp
, tp
, linenum
)
262 if (!*seg
|| !**seg
|| !***seg
)
264 if (!strcasecmp(**seg
, "port") && *(*seg
+ 1) && *(*seg
+ 2)) {
266 if (!strcmp(**seg
, "=") || !strcasecmp(**seg
, "eq"))
268 else if (!strcmp(**seg
, "!=") || !strcasecmp(**seg
, "ne"))
270 else if (!strcmp(**seg
, "<") || !strcasecmp(**seg
, "lt"))
272 else if (!strcmp(**seg
, ">") || !strcasecmp(**seg
, "gt"))
274 else if (!strcmp(**seg
, "<=") || !strcasecmp(**seg
, "le"))
276 else if (!strcmp(**seg
, ">=") || !strcasecmp(**seg
, "ge"))
278 else if (isalnum(***seg
) && *(*seg
+ 2)) {
279 if (portnum(**seg
, pp
, linenum
) == 0)
282 if (!strcmp(**seg
, "<>"))
284 else if (!strcmp(**seg
, "><"))
288 "%d: unknown range operator (%s)\n",
294 fprintf(stderr
, "%d: missing 2nd port value\n",
298 if (portnum(**seg
, tp
, linenum
) == 0)
301 fprintf(stderr
, "%d: unknown comparator (%s)\n",
305 if (comp
!= FR_OUTRANGE
&& comp
!= FR_INRANGE
) {
307 if (portnum(**seg
, pp
, linenum
) == 0)
318 * find the port number given by the name, either from getservbyname() or
319 * straight atoi(). Return 1 on success, 0 on failure
321 int portnum(name
, port
, linenum
)
326 struct servent
*sp
, *sp2
;
330 if (isdigit(*name
)) {
331 if (ratoi(name
, &i
, 0, USHRT_MAX
)) {
335 fprintf(stderr
, "%d: unknown port \"%s\"\n", linenum
, name
);
338 if (proto
!= NULL
&& strcasecmp(proto
, "tcp/udp") != 0) {
339 sp
= getservbyname(name
, proto
);
341 *port
= ntohs(sp
->s_port
);
344 fprintf(stderr
, "%d: unknown service \"%s\".\n", linenum
, name
);
347 sp
= getservbyname(name
, "tcp");
350 sp2
= getservbyname(name
, "udp");
352 fprintf(stderr
, "%d: unknown tcp/udp service \"%s\".\n",
356 if (p1
!= sp2
->s_port
) {
357 fprintf(stderr
, "%d: %s %d/tcp is a different port to ",
359 fprintf(stderr
, "%d: %s %d/udp\n", linenum
, name
, sp
->s_port
);
367 u_char
tcp_flags(flgs
, mask
, linenum
)
372 u_char tcpf
= 0, tcpfm
= 0, *fp
= &tcpf
;
376 s
= strchr(flgs
, '/');
379 tcpf
= strtol(flgs
, NULL
, 0);
385 if (*s
== '/' && fp
== &tcpf
) {
391 if (!(t
= index(flagset
, *s
))) {
392 fprintf(stderr
, "%d: unknown flag (%c)\n", linenum
, *s
);
395 *fp
|= flags
[t
- flagset
];
399 tcpfm
= strtol(s
, NULL
, 0);
403 tcpfm
= 0xff & ~(TH_ECN
|TH_CWR
);
405 tcpfm
= 0xff & ~(TH_ECN
);
413 * count consecutive 1's in bit mask. If the mask generated by counting
414 * consecutive 1's is different to that passed, return -1, else return #
423 ip
= ipn
= ntohl(ip
);
424 for (i
= 32; i
; i
--, ipn
*= 2)
425 if (ipn
& 0x80000000)
430 for (i
= 32, j
= cnt
; i
; i
--, j
--) {
447 for (k
= 3; k
>= 0; k
--)
448 if (msk
[k
] == 0xffffffff)
451 for (j
= msk
[k
]; j
; j
<<= 1)
459 char *portname(pr
, port
)
463 struct protoent
*p
= NULL
;
464 struct servent
*sv
= NULL
, *sv1
= NULL
;
467 if ((sv
= getservbyport(htons(port
), "tcp"))) {
468 strncpy(buf
, sv
->s_name
, sizeof(buf
)-1);
469 buf
[sizeof(buf
)-1] = '\0';
470 sv1
= getservbyport(htons(port
), "udp");
471 sv
= strncasecmp(buf
, sv
->s_name
, strlen(buf
)) ?
476 } else if (pr
&& (p
= getprotobynumber(pr
))) {
477 if ((sv
= getservbyport(htons(port
), p
->p_name
))) {
478 strncpy(buf
, sv
->s_name
, sizeof(buf
)-1);
479 buf
[sizeof(buf
)-1] = '\0';
484 (void) sprintf(buf
, "%d", port
);
489 int ratoi(ps
, pi
, min
, max
)
496 i
= (int)strtol(ps
, &pe
, 0);
497 if (*pe
!= '\0' || i
< min
|| i
> max
)
504 int ratoui(ps
, pi
, min
, max
)
511 i
= (u_int
)strtol(ps
, &pe
, 0);
512 if (*pe
!= '\0' || i
< min
|| i
> max
)
519 void printhostmask(v
, addr
, mask
)
528 ones
= count6bits(mask
);
529 if (ones
== 0 && !addr
[0] && !addr
[1] && !addr
[2] && !addr
[3])
534 inet_ntop(AF_INET6
, addr
, ipbuf
, sizeof(ipbuf
)),
540 if (!*addr
&& !*mask
)
544 printf("%s", inet_ntoa(ipa
));
545 if ((ones
= countbits(*mask
)) == -1) {
547 printf("/%s", inet_ntoa(ipa
));
554 void printportcmp(pr
, frp
)
558 static char *pcmp1
[] = { "*", "=", "!=", "<", ">", "<=", ">=",
561 if (frp
->frp_cmp
== FR_INRANGE
|| frp
->frp_cmp
== FR_OUTRANGE
)
562 printf(" port %d %s %d", frp
->frp_port
,
563 pcmp1
[frp
->frp_cmp
], frp
->frp_top
);
565 printf(" port %s %s", pcmp1
[frp
->frp_cmp
],
566 portname(pr
, frp
->frp_port
));
570 void printbuf(buf
, len
, zend
)
577 for (s
= buf
, i
= len
; i
; i
--) {
583 if ((c
== '\0') && zend
)
590 char *hostname(v
, ip
)
595 static char hostbuf
[MAXHOSTNAMELEN
+1];
600 ipa
.s_addr
= *(u_32_t
*)ip
;
601 return inet_ntoa(ipa
);
604 (void) inet_ntop(AF_INET6
, ip
, hostbuf
, sizeof(hostbuf
) - 1);
605 hostbuf
[MAXHOSTNAMELEN
] = '\0';