1 /* $NetBSD: ipft_tx.c,v 1.7 2007/04/14 20:34:28 martin Exp $ */
4 * Copyright (C) 2000-2006 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
8 * Id: ipft_tx.c,v 1.15.2.10 2007/09/03 21:54:44 darrenr Exp
11 static const char sccsid
[] = "@(#)ipft_tx.c 1.7 6/5/96 (C) 1993 Darren Reed";
12 static const char rcsid
[] = "@(#)Id: ipft_tx.c,v 1.15.2.10 2007/09/03 21:54:44 darrenr Exp";
21 #include <netinet/ip_var.h>
23 #include <netinet/tcpip.h>
28 static char *tx_proto
= "";
30 static int text_open
__P((char *)), text_close
__P((void));
31 static int text_readip
__P((char *, int, char **, int *));
32 static int parseline
__P((char *, ip_t
*, char **, int *));
34 static char myflagset
[] = "FSRPAUEC";
35 static u_char myflags
[] = { TH_FIN
, TH_SYN
, TH_RST
, TH_PUSH
,
36 TH_ACK
, TH_URG
, TH_ECN
, TH_CWR
};
38 struct ipread iptext
= { text_open
, text_close
, text_readip
, R_DO_CKSUM
};
39 static FILE *tfp
= NULL
;
42 static u_32_t tx_hostnum
__P((char *, int *));
43 static u_short tx_portnum
__P((char *));
47 * returns an ip address as a long var as a result of either a DNS lookup or
48 * straight inet_addr() call
50 static u_32_t
tx_hostnum(host
, resolved
)
57 if (!strcasecmp("any", host
))
60 return inet_addr(host
);
62 if (gethost(host
, &ipa
) == -1) {
64 fprintf(stderr
, "can't resolve hostname: %s\n", host
);
72 * find the port number given by the name, either from getservbyname() or
75 static u_short
tx_portnum(name
)
81 return (u_short
)atoi(name
);
82 sp
= getservbyname(name
, tx_proto
);
84 return ntohs(sp
->s_port
);
85 (void) fprintf(stderr
, "unknown service \"%s\".\n", name
);
90 char *tx_icmptypes
[] = {
91 "echorep", (char *)NULL
, (char *)NULL
, "unreach", "squench",
92 "redir", (char *)NULL
, (char *)NULL
, "echo", "routerad",
93 "routersol", "timex", "paramprob", "timest", "timestrep",
94 "inforeq", "inforep", "maskreq", "maskrep", "END"
97 static int text_open(fname
)
100 if (tfp
&& tfd
!= -1) {
105 if (!strcmp(fname
, "-")) {
109 tfd
= open(fname
, O_RDONLY
);
111 tfp
= fdopen(tfd
, "r");
117 static int text_close()
126 static int text_readip(buf
, cnt
, ifn
, dir
)
135 while (fgets(line
, sizeof(line
)-1, tfp
)) {
136 if ((s
= strchr(line
, '\n')))
138 if ((s
= strchr(line
, '\r')))
140 if ((s
= strchr(line
, '#')))
144 if ((opts
& OPT_DEBUG
) != 0)
145 printf("input: %s\n", line
);
148 if (!parseline(line
, (ip_t
*)buf
, ifn
, dir
)) {
150 return ntohs(ip
->ip_len
);
158 static int parseline(line
, ip
, ifn
, out
)
164 tcphdr_t th
, *tcp
= &th
;
165 struct icmp icmp
, *ic
= &icmp
;
166 char *cps
[20], **cpp
, c
, ipopts
[68];
171 bzero((char *)ip
, MAX(sizeof(*tcp
), sizeof(*ic
)) + sizeof(*ip
));
172 bzero((char *)tcp
, sizeof(*tcp
));
173 bzero((char *)ic
, sizeof(*ic
));
174 bzero(ipopts
, sizeof(ipopts
));
175 IP_HL_A(ip
, sizeof(*ip
) >> 2);
176 IP_V_A(ip
, IPVERSION
);
177 for (i
= 0, cps
[0] = strtok(line
, " \b\t\r\n"); cps
[i
] && i
< 19; )
178 cps
[++i
] = strtok(NULL
, " \b\t\r\n");
185 if (!ISALPHA(c
) || (TOLOWER(c
) != 'o' && TOLOWER(c
) != 'i')) {
186 fprintf(stderr
, "bad direction \"%s\"\n", *cpp
);
189 *out
= (TOLOWER(c
) == 'o') ? 1 : 0;
194 if (!strcasecmp(*cpp
, "on")) {
198 *ifn
= strdup(*cpp
++);
204 ip
->ip_len
= sizeof(ip_t
);
205 if (!strcasecmp(*cpp
, "tcp") || !strcasecmp(*cpp
, "udp") ||
206 !strcasecmp(*cpp
, "icmp")) {
208 ip
->ip_p
= IPPROTO_TCP
;
209 ip
->ip_len
+= sizeof(struct tcphdr
);
211 } else if (c
== 'u') {
212 ip
->ip_p
= IPPROTO_UDP
;
213 ip
->ip_len
+= sizeof(struct udphdr
);
216 ip
->ip_p
= IPPROTO_ICMP
;
217 ip
->ip_len
+= ICMPERR_IPICMPHLEN
;
221 } else if (ISDIGIT(**cpp
) && !index(*cpp
, '.')) {
222 ip
->ip_p
= atoi(*cpp
);
225 ip
->ip_p
= IPPROTO_IP
;
229 if (ip
->ip_p
== IPPROTO_TCP
|| ip
->ip_p
== IPPROTO_UDP
) {
232 last
= strchr(*cpp
, ',');
234 fprintf(stderr
, "tcp/udp with no source port\n");
238 tcp
->th_sport
= htons(tx_portnum(last
));
239 if (ip
->ip_p
== IPPROTO_TCP
) {
240 tcp
->th_win
= htons(4096);
241 TCP_OFF_A(tcp
, sizeof(*tcp
) >> 2);
244 ip
->ip_src
.s_addr
= tx_hostnum(*cpp
, &r
);
249 if (ip
->ip_p
== IPPROTO_TCP
|| ip
->ip_p
== IPPROTO_UDP
) {
252 last
= strchr(*cpp
, ',');
254 fprintf(stderr
, "tcp/udp with no destination port\n");
258 tcp
->th_dport
= htons(tx_portnum(last
));
260 ip
->ip_dst
.s_addr
= tx_hostnum(*cpp
, &r
);
262 if (ip
->ip_p
== IPPROTO_TCP
) {
267 for (s
= *cpp
; *s
; s
++)
268 if ((t
= strchr(myflagset
, *s
)))
269 tcp
->th_flags
|= myflags
[t
-myflagset
];
274 if (tcp
->th_flags
& TH_URG
)
275 tcp
->th_urp
= htons(1);
277 if (*cpp
&& !strncasecmp(*cpp
, "seq=", 4)) {
278 tcp
->th_seq
= htonl(atoi(*cpp
+ 4));
282 if (*cpp
&& !strncasecmp(*cpp
, "ack=", 4)) {
283 tcp
->th_ack
= htonl(atoi(*cpp
+ 4));
286 } else if (*cpp
&& ip
->ip_p
== IPPROTO_ICMP
) {
287 extern char *tx_icmptypes
[];
291 t
= strchr(*cpp
, ',');
295 for (s
= tx_icmptypes
, i
= 0; !*s
|| strcmp(*s
, "END");
297 if (*s
&& !strcasecmp(*cpp
, *s
)) {
300 ic
->icmp_code
= atoi(t
+ 1);
309 if (*cpp
&& !strcasecmp(*cpp
, "opt")) {
313 olen
= buildopts(*cpp
, ipopts
, (IP_HL(ip
) - 5) << 2);
315 bcopy(ipopts
, (char *)(ip
+ 1), olen
);
316 IP_HL_A(ip
, IP_HL(ip
) + (olen
>> 2));
319 if (ip
->ip_p
== IPPROTO_TCP
|| ip
->ip_p
== IPPROTO_UDP
)
320 bcopy((char *)tcp
, ((char *)ip
) + (IP_HL(ip
) << 2),
322 else if (ip
->ip_p
== IPPROTO_ICMP
)
323 bcopy((char *)ic
, ((char *)ip
) + (IP_HL(ip
) << 2),
325 ip
->ip_len
= htons(ip
->ip_len
);