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';