2 * Copyright (C) 1995-2001 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
6 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
7 * Use is subject to license terms.
10 static const char sccsid
[] = "@(#)ipft_tx.c 1.7 6/5/96 (C) 1993 Darren Reed";
11 static const char rcsid
[] = "@(#)$Id: ipft_tx.c,v 1.15.2.3 2005/06/18 02:41:34 darrenr Exp $";
19 #include <netinet/ip_var.h>
21 #include <netinet/tcpip.h>
26 static char *tx_proto
= "";
28 static int text_open
__P((char *)), text_close
__P((void));
29 static int text_readip
__P((char *, int, char **, int *));
30 static int parseline
__P((char *, ip_t
*, char **, int *));
32 static char myflagset
[] = "FSRPAUEC";
33 static u_char myflags
[] = { TH_FIN
, TH_SYN
, TH_RST
, TH_PUSH
,
34 TH_ACK
, TH_URG
, TH_ECN
, TH_CWR
};
36 struct ipread iptext
= { text_open
, text_close
, text_readip
, R_DO_CKSUM
};
37 static FILE *tfp
= NULL
;
40 static u_32_t tx_hostnum
__P((char *, int *));
41 static u_short tx_portnum
__P((char *));
45 * returns an ip address as a long var as a result of either a DNS lookup or
46 * straight inet_addr() call
48 static u_32_t
tx_hostnum(host
, resolved
)
55 if (!strcasecmp("any", host
))
58 return inet_addr(host
);
60 if (gethost(host
, &ipa
, 0) == -1) {
62 fprintf(stderr
, "can't resolve hostname: %s\n", host
);
70 * find the port number given by the name, either from getservbyname() or
73 static u_short
tx_portnum(name
)
76 struct servent
*sp
, *sp2
;
80 return (u_short
)atoi(name
);
83 if (strcasecmp(tx_proto
, "tcp/udp")) {
84 sp
= getservbyname(name
, tx_proto
);
86 return ntohs(sp
->s_port
);
87 (void) fprintf(stderr
, "unknown service \"%s\".\n", name
);
90 sp
= getservbyname(name
, "tcp");
93 sp2
= getservbyname(name
, "udp");
95 (void) fprintf(stderr
, "unknown tcp/udp service \"%s\".\n",
99 if (p1
!= sp2
->s_port
) {
100 (void) fprintf(stderr
, "%s %d/tcp is a different port to ",
102 (void) fprintf(stderr
, "%s %d/udp\n", name
, sp
->s_port
);
109 char *tx_icmptypes
[] = {
110 "echorep", NULL
, NULL
, "unreach", "squench",
111 "redir", NULL
, NULL
, "echo", "routerad",
112 "routersol", "timex", "paramprob", "timest", "timestrep",
113 "inforeq", "inforep", "maskreq", "maskrep", "END"
116 static int text_open(fname
)
119 if (tfp
&& tfd
!= -1) {
124 if (!strcmp(fname
, "-")) {
128 tfd
= open(fname
, O_RDONLY
);
130 tfp
= fdopen(tfd
, "r");
136 static int text_close()
145 static int text_readip(buf
, cnt
, ifn
, dir
)
153 while (fgets(line
, sizeof(line
)-1, tfp
)) {
154 if ((s
= strchr(line
, '\n')))
156 if ((s
= strchr(line
, '\r')))
158 if ((s
= strchr(line
, '#')))
162 if (!(opts
& OPT_BRIEF
))
163 printf("input: %s\n", line
);
166 if (!parseline(line
, (ip_t
*)buf
, ifn
, dir
))
168 return sizeof(ip_t
) + sizeof(tcphdr_t
);
176 static int parseline(line
, ip
, ifn
, out
)
182 tcphdr_t th
, *tcp
= &th
;
183 struct icmp icmp
, *ic
= &icmp
;
184 char *cps
[20], **cpp
, c
, ipopts
[68];
188 bzero((char *)ip
, MAX(sizeof(*tcp
), sizeof(*ic
)) + sizeof(*ip
));
189 bzero((char *)tcp
, sizeof(*tcp
));
190 bzero((char *)ic
, sizeof(*ic
));
191 bzero(ipopts
, sizeof(ipopts
));
192 IP_HL_A(ip
, sizeof(*ip
) >> 2);
193 IP_V_A(ip
, IPVERSION
);
194 for (i
= 0, cps
[0] = strtok(line
, " \b\t\r\n"); cps
[i
] && i
< 19; )
195 cps
[++i
] = strtok(NULL
, " \b\t\r\n");
202 if (!ISALPHA(c
) || (TOLOWER(c
) != 'o' && TOLOWER(c
) != 'i')) {
203 fprintf(stderr
, "bad direction \"%s\"\n", *cpp
);
206 *out
= (TOLOWER(c
) == 'o') ? 1 : 0;
211 if (!strcasecmp(*cpp
, "on")) {
215 *ifn
= strdup(*cpp
++);
221 ip
->ip_len
= sizeof(ip_t
);
222 if (!strcasecmp(*cpp
, "tcp") || !strcasecmp(*cpp
, "udp") ||
223 !strcasecmp(*cpp
, "icmp")) {
225 ip
->ip_p
= IPPROTO_TCP
;
226 ip
->ip_len
+= sizeof(struct tcphdr
);
228 } else if (c
== 'u') {
229 ip
->ip_p
= IPPROTO_UDP
;
230 ip
->ip_len
+= sizeof(struct udphdr
);
233 ip
->ip_p
= IPPROTO_ICMP
;
234 ip
->ip_len
+= ICMPERR_IPICMPHLEN
;
238 } else if (ISDIGIT(**cpp
) && !index(*cpp
, '.')) {
239 ip
->ip_p
= atoi(*cpp
);
242 ip
->ip_p
= IPPROTO_IP
;
246 if (ip
->ip_p
== IPPROTO_TCP
|| ip
->ip_p
== IPPROTO_UDP
) {
249 last
= strchr(*cpp
, ',');
251 fprintf(stderr
, "tcp/udp with no source port\n");
255 tcp
->th_sport
= htons(tx_portnum(last
));
256 if (ip
->ip_p
== IPPROTO_TCP
) {
257 tcp
->th_win
= htons(4096);
258 TCP_OFF_A(tcp
, sizeof(*tcp
) >> 2);
261 ip
->ip_src
.s_addr
= tx_hostnum(*cpp
, &r
);
266 if (ip
->ip_p
== IPPROTO_TCP
|| ip
->ip_p
== IPPROTO_UDP
) {
269 last
= strchr(*cpp
, ',');
271 fprintf(stderr
, "tcp/udp with no destination port\n");
275 tcp
->th_dport
= htons(tx_portnum(last
));
277 ip
->ip_dst
.s_addr
= tx_hostnum(*cpp
, &r
);
279 if (*cpp
&& ip
->ip_p
== IPPROTO_TCP
) {
283 for (s
= *cpp
; *s
; s
++)
284 if ((t
= strchr(myflagset
, *s
)))
285 tcp
->th_flags
|= myflags
[t
- myflagset
];
288 if (tcp
->th_flags
== 0)
290 if (tcp
->th_flags
& TH_URG
)
291 tcp
->th_urp
= htons(1);
292 } else if (*cpp
&& ip
->ip_p
== IPPROTO_ICMP
) {
293 extern char *tx_icmptypes
[];
297 for (s
= tx_icmptypes
, i
= 0; !*s
|| strcmp(*s
, "END");
299 if (*s
&& !strncasecmp(*cpp
, *s
, strlen(*s
))) {
301 if ((t
= strchr(*cpp
, ',')))
302 ic
->icmp_code
= atoi(t
+1);
308 if (*cpp
&& !strcasecmp(*cpp
, "opt")) {
312 olen
= buildopts(*cpp
, ipopts
, (IP_HL(ip
) - 5) << 2);
314 bcopy(ipopts
, (char *)(ip
+ 1), olen
);
315 IP_HL_A(ip
, IP_HL(ip
) + (olen
>> 2));
318 if (ip
->ip_p
== IPPROTO_TCP
|| ip
->ip_p
== IPPROTO_UDP
)
319 bcopy((char *)tcp
, ((char *)ip
) + (IP_HL(ip
) << 2),
321 else if (ip
->ip_p
== IPPROTO_ICMP
)
322 bcopy((char *)ic
, ((char *)ip
) + (IP_HL(ip
) << 2),
324 ip
->ip_len
= htons(ip
->ip_len
);