xref: /freebsd/sbin/ipf/iplang/iplang_y.y (revision 2a63c3be)
141edb306SCy Schubert 
241edb306SCy Schubert %{
341edb306SCy Schubert /*
441edb306SCy Schubert  * Copyright (C) 2012 by Darren Reed.
541edb306SCy Schubert  *
641edb306SCy Schubert  * See the IPFILTER.LICENCE file for details on licencing.
741edb306SCy Schubert  *
841edb306SCy Schubert  * Id: iplang_y.y,v 2.9.2.4 2006/03/17 12:11:29 darrenr Exp $
941edb306SCy Schubert  */
1041edb306SCy Schubert 
1141edb306SCy Schubert #include <stdio.h>
1241edb306SCy Schubert #include <string.h>
1341edb306SCy Schubert #include <fcntl.h>
1441edb306SCy Schubert #if !defined(__SVR4) && !defined(__svr4__)
1541edb306SCy Schubert # include <strings.h>
1641edb306SCy Schubert #else
1741edb306SCy Schubert # include <sys/byteorder.h>
1841edb306SCy Schubert #endif
1941edb306SCy Schubert #include <sys/types.h>
2041edb306SCy Schubert #include <sys/stat.h>
2141edb306SCy Schubert #include <sys/param.h>
2241edb306SCy Schubert #include <sys/time.h>
2341edb306SCy Schubert #include <stdlib.h>
2441edb306SCy Schubert #include <unistd.h>
2541edb306SCy Schubert #include <stddef.h>
2641edb306SCy Schubert #include <sys/socket.h>
2741edb306SCy Schubert #include <net/if.h>
2841edb306SCy Schubert #include <netinet/in.h>
2941edb306SCy Schubert #include <netinet/in_systm.h>
3041edb306SCy Schubert #include <netinet/ip.h>
3141edb306SCy Schubert # include <netinet/ip_var.h>
3241edb306SCy Schubert # include <net/route.h>
3341edb306SCy Schubert # include <netinet/if_ether.h>
3441edb306SCy Schubert #include <netdb.h>
3541edb306SCy Schubert #include <arpa/nameser.h>
3641edb306SCy Schubert #include <arpa/inet.h>
3741edb306SCy Schubert #include <resolv.h>
3841edb306SCy Schubert #include <ctype.h>
3941edb306SCy Schubert #include "ipsend.h"
4041edb306SCy Schubert #include "ip_compat.h"
4141edb306SCy Schubert #include "ipf.h"
4241edb306SCy Schubert #include "iplang.h"
4341edb306SCy Schubert 
4441edb306SCy Schubert extern	int	opts;
4541edb306SCy Schubert extern	struct ipopt_names ionames[];
4641edb306SCy Schubert extern	int	state, state, lineNum, token;
4741edb306SCy Schubert extern	int	yylineno;
4841edb306SCy Schubert extern	char	yytext[];
4941edb306SCy Schubert extern	FILE	*yyin;
5041edb306SCy Schubert int	yylex	__P((void));
5141edb306SCy Schubert #define	YYDEBUG 1
5241edb306SCy Schubert int	yydebug = 1;
5341edb306SCy Schubert 
5441edb306SCy Schubert iface_t *iflist = NULL, **iftail = &iflist;
5541edb306SCy Schubert iface_t *cifp = NULL;
5641edb306SCy Schubert arp_t *arplist = NULL, **arptail = &arplist, *carp = NULL;
5741edb306SCy Schubert struct in_addr defrouter;
5841edb306SCy Schubert send_t	sending;
5941edb306SCy Schubert char	*sclass = NULL;
6041edb306SCy Schubert u_short	c_chksum(u_short *, u_int, u_long);
6141edb306SCy Schubert u_long	p_chksum(u_short *, u_int);
6241edb306SCy Schubert 
6341edb306SCy Schubert u_long	ipbuffer[67584/sizeof(u_long)];		/* 66K */
6441edb306SCy Schubert aniphdr_t	*aniphead = NULL, *canip = NULL, **aniptail = &aniphead;
6541edb306SCy Schubert ip_t		*ip = NULL;
6641edb306SCy Schubert udphdr_t	*udp = NULL;
6741edb306SCy Schubert tcphdr_t	*tcp = NULL;
6841edb306SCy Schubert icmphdr_t	*icmp = NULL;
6941edb306SCy Schubert 
7041edb306SCy Schubert struct statetoopt {
7141edb306SCy Schubert 	int	sto_st;
7241edb306SCy Schubert 	int	sto_op;
7341edb306SCy Schubert };
7441edb306SCy Schubert 
7541edb306SCy Schubert struct	in_addr getipv4addr(char *arg);
7641edb306SCy Schubert u_short	getportnum(char *, char *);
7741edb306SCy Schubert struct	ether_addr *geteaddr(char *, struct ether_addr *);
7841edb306SCy Schubert void	*new_header(int);
7941edb306SCy Schubert void	free_aniplist(void);
8041edb306SCy Schubert void	inc_anipheaders(int);
8141edb306SCy Schubert void	new_data(void);
8241edb306SCy Schubert void	set_datalen(char **);
8341edb306SCy Schubert void	set_datafile(char **);
8441edb306SCy Schubert void	set_data(char **);
8541edb306SCy Schubert void	new_packet(void);
8641edb306SCy Schubert void	set_ipv4proto(char **);
8741edb306SCy Schubert void	set_ipv4src(char **);
8841edb306SCy Schubert void	set_ipv4dst(char **);
8941edb306SCy Schubert void	set_ipv4off(char **);
9041edb306SCy Schubert void	set_ipv4v(char **);
9141edb306SCy Schubert void	set_ipv4hl(char **);
9241edb306SCy Schubert void	set_ipv4ttl(char **);
9341edb306SCy Schubert void	set_ipv4tos(char **);
9441edb306SCy Schubert void	set_ipv4id(char **);
9541edb306SCy Schubert void	set_ipv4sum(char **);
9641edb306SCy Schubert void	set_ipv4len(char **);
9741edb306SCy Schubert void	new_tcpheader(void);
9841edb306SCy Schubert void	set_tcpsport(char **);
9941edb306SCy Schubert void	set_tcpdport(char **);
10041edb306SCy Schubert void	set_tcpseq(char **);
10141edb306SCy Schubert void	set_tcpack(char **);
10241edb306SCy Schubert void	set_tcpoff(char **);
10341edb306SCy Schubert void	set_tcpurp(char **);
10441edb306SCy Schubert void	set_tcpwin(char **);
10541edb306SCy Schubert void	set_tcpsum(char **);
10641edb306SCy Schubert void	set_tcpflags(char **);
10741edb306SCy Schubert void	set_tcpopt(int, char **);
10841edb306SCy Schubert void	end_tcpopt(void);
10941edb306SCy Schubert void	new_udpheader(void);
11041edb306SCy Schubert void	set_udplen(char **);
11141edb306SCy Schubert void	set_udpsum(char **);
11241edb306SCy Schubert void	prep_packet(void);
11341edb306SCy Schubert void	packet_done(void);
11441edb306SCy Schubert void	new_interface(void);
11541edb306SCy Schubert void	check_interface(void);
11641edb306SCy Schubert void	set_ifname(char **);
11741edb306SCy Schubert void	set_ifmtu(int);
11841edb306SCy Schubert void	set_ifv4addr(char **);
11941edb306SCy Schubert void	set_ifeaddr(char **);
12041edb306SCy Schubert void	new_arp(void);
12141edb306SCy Schubert void	set_arpeaddr(char **);
12241edb306SCy Schubert void	set_arpv4addr(char **);
12341edb306SCy Schubert void	reset_send(void);
12441edb306SCy Schubert void	set_sendif(char **);
12541edb306SCy Schubert void	set_sendvia(char **);
12641edb306SCy Schubert void	set_defaultrouter(char **);
12741edb306SCy Schubert void	new_icmpheader(void);
12841edb306SCy Schubert void	set_icmpcode(int);
12941edb306SCy Schubert void	set_icmptype(int);
13041edb306SCy Schubert void	set_icmpcodetok(char **);
13141edb306SCy Schubert void	set_icmptypetok(char **);
13241edb306SCy Schubert void	set_icmpid(int);
13341edb306SCy Schubert void	set_icmpseq(int);
13441edb306SCy Schubert void	set_icmpotime(int);
13541edb306SCy Schubert void	set_icmprtime(int);
13641edb306SCy Schubert void	set_icmpttime(int);
13741edb306SCy Schubert void	set_icmpmtu(int);
13841edb306SCy Schubert void	set_redir(int, char **);
13941edb306SCy Schubert void	new_ipv4opt(void);
14041edb306SCy Schubert void	set_icmppprob(int);
14141edb306SCy Schubert void	add_ipopt(int, void *);
14241edb306SCy Schubert void	end_ipopt(void);
14341edb306SCy Schubert void	set_secclass(char **);
14441edb306SCy Schubert void	free_anipheader(void);
14541edb306SCy Schubert void	end_ipv4(void);
14641edb306SCy Schubert void	end_icmp(void);
14741edb306SCy Schubert void	end_udp(void);
14841edb306SCy Schubert void	end_tcp(void);
14941edb306SCy Schubert void	end_data(void);
15041edb306SCy Schubert void	yyerror(char *);
15141edb306SCy Schubert void	iplang(FILE *);
15241edb306SCy Schubert int	arp_getipv4(char *, char *);
15341edb306SCy Schubert int	yyparse(void);
15441edb306SCy Schubert %}
15541edb306SCy Schubert %union {
15641edb306SCy Schubert 	char	*str;
15741edb306SCy Schubert 	int	num;
15841edb306SCy Schubert }
15941edb306SCy Schubert %token	<num> IL_NUMBER
16041edb306SCy Schubert %type	<num> number digits optnumber
16141edb306SCy Schubert %token	<str> IL_TOKEN
16241edb306SCy Schubert %type	<str> token optoken
16341edb306SCy Schubert %token	IL_HEXDIGIT IL_COLON IL_DOT IL_EOF IL_COMMENT
16441edb306SCy Schubert %token	IL_INTERFACE IL_IFNAME IL_MTU IL_EADDR
16541edb306SCy Schubert %token	IL_IPV4 IL_V4PROTO IL_V4SRC IL_V4DST IL_V4OFF IL_V4V IL_V4HL IL_V4TTL
16641edb306SCy Schubert %token	IL_V4TOS IL_V4SUM IL_V4LEN IL_V4OPT IL_V4ID
16741edb306SCy Schubert %token	IL_TCP IL_SPORT IL_DPORT IL_TCPFL IL_TCPSEQ IL_TCPACK IL_TCPOFF
16841edb306SCy Schubert %token	IL_TCPWIN IL_TCPSUM IL_TCPURP IL_TCPOPT IL_TCPO_NOP IL_TCPO_EOL
16941edb306SCy Schubert %token	IL_TCPO_MSS IL_TCPO_WSCALE IL_TCPO_TS
17041edb306SCy Schubert %token	IL_UDP IL_UDPLEN IL_UDPSUM
17141edb306SCy Schubert %token	IL_ICMP IL_ICMPTYPE IL_ICMPCODE
17241edb306SCy Schubert %token	IL_SEND IL_VIA
17341edb306SCy Schubert %token	IL_ARP
17441edb306SCy Schubert %token	IL_DEFROUTER
17541edb306SCy Schubert %token	IL_SUM IL_OFF IL_LEN IL_V4ADDR IL_OPT
17641edb306SCy Schubert %token	IL_DATA IL_DLEN IL_DVALUE IL_DFILE
17741edb306SCy Schubert %token	IL_IPO_NOP IL_IPO_RR IL_IPO_ZSU IL_IPO_MTUP IL_IPO_MTUR IL_IPO_EOL
17841edb306SCy Schubert %token	IL_IPO_TS IL_IPO_TR IL_IPO_SEC IL_IPO_LSRR IL_IPO_ESEC
17941edb306SCy Schubert %token	IL_IPO_SATID IL_IPO_SSRR IL_IPO_ADDEXT IL_IPO_VISA IL_IPO_IMITD
18041edb306SCy Schubert %token	IL_IPO_EIP IL_IPO_FINN IL_IPO_SECCLASS IL_IPO_CIPSO IL_IPO_ENCODE
18141edb306SCy Schubert %token	<str> IL_IPS_RESERV4 IL_IPS_TOPSECRET IL_IPS_SECRET IL_IPS_RESERV3
18241edb306SCy Schubert %token	<str> IL_IPS_CONFID IL_IPS_UNCLASS IL_IPS_RESERV2 IL_IPS_RESERV1
18341edb306SCy Schubert %token	IL_ICMP_ECHOREPLY IL_ICMP_UNREACH IL_ICMP_UNREACH_NET
18441edb306SCy Schubert %token	IL_ICMP_UNREACH_HOST IL_ICMP_UNREACH_PROTOCOL IL_ICMP_UNREACH_PORT
18541edb306SCy Schubert %token	IL_ICMP_UNREACH_NEEDFRAG IL_ICMP_UNREACH_SRCFAIL
18641edb306SCy Schubert %token	IL_ICMP_UNREACH_NET_UNKNOWN IL_ICMP_UNREACH_HOST_UNKNOWN
18741edb306SCy Schubert %token	IL_ICMP_UNREACH_ISOLATED IL_ICMP_UNREACH_NET_PROHIB
18841edb306SCy Schubert %token	IL_ICMP_UNREACH_HOST_PROHIB IL_ICMP_UNREACH_TOSNET
18941edb306SCy Schubert %token	IL_ICMP_UNREACH_TOSHOST IL_ICMP_UNREACH_FILTER_PROHIB
19041edb306SCy Schubert %token	IL_ICMP_UNREACH_HOST_PRECEDENCE IL_ICMP_UNREACH_PRECEDENCE_CUTOFF
19141edb306SCy Schubert %token	IL_ICMP_SOURCEQUENCH IL_ICMP_REDIRECT IL_ICMP_REDIRECT_NET
19241edb306SCy Schubert %token	IL_ICMP_REDIRECT_HOST IL_ICMP_REDIRECT_TOSNET
19341edb306SCy Schubert %token	IL_ICMP_REDIRECT_TOSHOST IL_ICMP_ECHO IL_ICMP_ROUTERADVERT
19441edb306SCy Schubert %token	IL_ICMP_ROUTERSOLICIT IL_ICMP_TIMXCEED IL_ICMP_TIMXCEED_INTRANS
19541edb306SCy Schubert %token	IL_ICMP_TIMXCEED_REASS IL_ICMP_PARAMPROB IL_ICMP_PARAMPROB_OPTABSENT
19641edb306SCy Schubert %token	IL_ICMP_TSTAMP IL_ICMP_TSTAMPREPLY IL_ICMP_IREQ IL_ICMP_IREQREPLY
19741edb306SCy Schubert %token	IL_ICMP_MASKREQ IL_ICMP_MASKREPLY IL_ICMP_SEQ IL_ICMP_ID
19841edb306SCy Schubert %token	IL_ICMP_OTIME IL_ICMP_RTIME IL_ICMP_TTIME
19941edb306SCy Schubert 
20041edb306SCy Schubert %%
20141edb306SCy Schubert file:	line
20241edb306SCy Schubert 	| line file
20341edb306SCy Schubert 	| IL_COMMENT
20441edb306SCy Schubert 	| IL_COMMENT file
20541edb306SCy Schubert 	;
20641edb306SCy Schubert 
20741edb306SCy Schubert line:	iface
20841edb306SCy Schubert 	| arp
20941edb306SCy Schubert 	| send
21041edb306SCy Schubert 	| defrouter
21141edb306SCy Schubert 	| ipline
21241edb306SCy Schubert 	;
21341edb306SCy Schubert 
21441edb306SCy Schubert iface:  ifhdr '{' ifaceopts '}' ';'	{ check_interface(); }
21541edb306SCy Schubert 	;
21641edb306SCy Schubert 
21741edb306SCy Schubert ifhdr:	IL_INTERFACE			{ new_interface(); }
21841edb306SCy Schubert 	;
21941edb306SCy Schubert 
22041edb306SCy Schubert ifaceopts:
22141edb306SCy Schubert 	ifaceopt
22241edb306SCy Schubert 	| ifaceopt ifaceopts
22341edb306SCy Schubert 	;
22441edb306SCy Schubert 
22541edb306SCy Schubert ifaceopt:
22641edb306SCy Schubert 	IL_IFNAME token			{ set_ifname(&$2); }
22741edb306SCy Schubert 	| IL_MTU number			{ set_ifmtu($2); }
22841edb306SCy Schubert 	| IL_V4ADDR token		{ set_ifv4addr(&$2); }
22941edb306SCy Schubert 	| IL_EADDR token		{ set_ifeaddr(&$2); }
23041edb306SCy Schubert 	;
23141edb306SCy Schubert 
23241edb306SCy Schubert send:   sendhdr '{' sendbody '}' ';'	{ packet_done(); }
23341edb306SCy Schubert 	| sendhdr ';'			{ packet_done(); }
23441edb306SCy Schubert 	;
23541edb306SCy Schubert 
23641edb306SCy Schubert sendhdr:
23741edb306SCy Schubert 	IL_SEND				{ reset_send(); }
23841edb306SCy Schubert 	;
23941edb306SCy Schubert 
24041edb306SCy Schubert sendbody:
24141edb306SCy Schubert 	sendopt
24241edb306SCy Schubert 	| sendbody sendopt
24341edb306SCy Schubert 	;
24441edb306SCy Schubert 
24541edb306SCy Schubert sendopt:
24641edb306SCy Schubert 	IL_IFNAME token			{ set_sendif(&$2); }
24741edb306SCy Schubert 	| IL_VIA token			{ set_sendvia(&$2); }
24841edb306SCy Schubert 	;
24941edb306SCy Schubert 
25041edb306SCy Schubert arp:    arphdr '{' arpbody '}' ';'
25141edb306SCy Schubert 	;
25241edb306SCy Schubert 
25341edb306SCy Schubert arphdr:	IL_ARP				{ new_arp(); }
25441edb306SCy Schubert 	;
25541edb306SCy Schubert 
25641edb306SCy Schubert arpbody:
25741edb306SCy Schubert 	arpopt
25841edb306SCy Schubert 	| arpbody arpopt
25941edb306SCy Schubert 	;
26041edb306SCy Schubert 
26141edb306SCy Schubert arpopt: IL_V4ADDR token			{ set_arpv4addr(&$2); }
26241edb306SCy Schubert 	| IL_EADDR token		{ set_arpeaddr(&$2); }
26341edb306SCy Schubert 	;
26441edb306SCy Schubert 
26541edb306SCy Schubert defrouter:
26641edb306SCy Schubert 	IL_DEFROUTER token		{ set_defaultrouter(&$2); }
26741edb306SCy Schubert 	;
26841edb306SCy Schubert 
26941edb306SCy Schubert bodyline:
27041edb306SCy Schubert 	ipline
27141edb306SCy Schubert 	| tcp tcpline
27241edb306SCy Schubert 	| udp udpline
27341edb306SCy Schubert 	| icmp icmpline
27441edb306SCy Schubert 	| data dataline
27541edb306SCy Schubert 	;
27641edb306SCy Schubert 
27741edb306SCy Schubert ipline:	ipv4 '{' ipv4body '}' ';'	{ end_ipv4(); }
27841edb306SCy Schubert 	;
27941edb306SCy Schubert 
28041edb306SCy Schubert ipv4:	IL_IPV4				{ new_packet(); }
28141edb306SCy Schubert 
28241edb306SCy Schubert ipv4body:
28341edb306SCy Schubert 	ipv4type
28441edb306SCy Schubert 	| ipv4type ipv4body
28541edb306SCy Schubert 	| bodyline
28641edb306SCy Schubert 	;
28741edb306SCy Schubert 
28841edb306SCy Schubert ipv4type:
28941edb306SCy Schubert 	IL_V4PROTO token		{ set_ipv4proto(&$2); }
29041edb306SCy Schubert 	| IL_V4SRC token		{ set_ipv4src(&$2); }
29141edb306SCy Schubert 	| IL_V4DST token		{ set_ipv4dst(&$2); }
29241edb306SCy Schubert 	| IL_V4OFF token		{ set_ipv4off(&$2); }
29341edb306SCy Schubert 	| IL_V4V token			{ set_ipv4v(&$2); }
29441edb306SCy Schubert 	| IL_V4HL token			{ set_ipv4hl(&$2); }
29541edb306SCy Schubert 	| IL_V4ID token			{ set_ipv4id(&$2); }
29641edb306SCy Schubert 	| IL_V4TTL token		{ set_ipv4ttl(&$2); }
29741edb306SCy Schubert 	| IL_V4TOS token		{ set_ipv4tos(&$2); }
29841edb306SCy Schubert 	| IL_V4SUM token		{ set_ipv4sum(&$2); }
29941edb306SCy Schubert 	| IL_V4LEN token		{ set_ipv4len(&$2); }
30041edb306SCy Schubert 	| ipv4opt '{' ipv4optlist '}' ';'	{ end_ipopt(); }
30141edb306SCy Schubert 	;
30241edb306SCy Schubert 
30341edb306SCy Schubert tcp:	IL_TCP				{ new_tcpheader(); }
30441edb306SCy Schubert 	;
30541edb306SCy Schubert 
30641edb306SCy Schubert tcpline:
30741edb306SCy Schubert 	'{' tcpheader '}' ';'		{ end_tcp(); }
30841edb306SCy Schubert 	;
30941edb306SCy Schubert 
31041edb306SCy Schubert tcpheader:
31141edb306SCy Schubert 	tcpbody
31241edb306SCy Schubert 	| tcpbody tcpheader
31341edb306SCy Schubert 	| bodyline
31441edb306SCy Schubert 	;
31541edb306SCy Schubert 
31641edb306SCy Schubert tcpbody:
31741edb306SCy Schubert 	IL_SPORT token			{ set_tcpsport(&$2); }
31841edb306SCy Schubert 	| IL_DPORT token		{ set_tcpdport(&$2); }
31941edb306SCy Schubert 	| IL_TCPSEQ token		{ set_tcpseq(&$2); }
32041edb306SCy Schubert 	| IL_TCPACK token		{ set_tcpack(&$2); }
32141edb306SCy Schubert 	| IL_TCPOFF token		{ set_tcpoff(&$2); }
32241edb306SCy Schubert 	| IL_TCPURP token		{ set_tcpurp(&$2); }
32341edb306SCy Schubert 	| IL_TCPWIN token		{ set_tcpwin(&$2); }
32441edb306SCy Schubert 	| IL_TCPSUM token		{ set_tcpsum(&$2); }
32541edb306SCy Schubert 	| IL_TCPFL token		{ set_tcpflags(&$2); }
32641edb306SCy Schubert 	| IL_TCPOPT '{' tcpopts '}' ';'	{ end_tcpopt(); }
32741edb306SCy Schubert 	;
32841edb306SCy Schubert 
32941edb306SCy Schubert tcpopts:
33041edb306SCy Schubert 	| tcpopt tcpopts
33141edb306SCy Schubert 	;
33241edb306SCy Schubert 
33341edb306SCy Schubert tcpopt:	IL_TCPO_NOP ';'			{ set_tcpopt(IL_TCPO_NOP, NULL); }
33441edb306SCy Schubert 	| IL_TCPO_EOL ';'		{ set_tcpopt(IL_TCPO_EOL, NULL); }
33541edb306SCy Schubert 	| IL_TCPO_MSS optoken		{ set_tcpopt(IL_TCPO_MSS,&$2);}
33641edb306SCy Schubert 	| IL_TCPO_WSCALE optoken	{ set_tcpopt(IL_TCPO_WSCALE,&$2);}
33741edb306SCy Schubert 	| IL_TCPO_TS optoken		{ set_tcpopt(IL_TCPO_TS, &$2);}
33841edb306SCy Schubert 	;
33941edb306SCy Schubert 
34041edb306SCy Schubert udp:	IL_UDP				{ new_udpheader(); }
34141edb306SCy Schubert 	;
34241edb306SCy Schubert 
34341edb306SCy Schubert udpline:
34441edb306SCy Schubert 	'{' udpheader '}' ';'		{ end_udp(); }
34541edb306SCy Schubert 	;
34641edb306SCy Schubert 
34741edb306SCy Schubert 
34841edb306SCy Schubert udpheader:
34941edb306SCy Schubert 	udpbody
35041edb306SCy Schubert 	| udpbody udpheader
35141edb306SCy Schubert 	| bodyline
35241edb306SCy Schubert 	;
35341edb306SCy Schubert 
35441edb306SCy Schubert udpbody:
35541edb306SCy Schubert 	IL_SPORT token			{ set_tcpsport(&$2); }
35641edb306SCy Schubert 	| IL_DPORT token		{ set_tcpdport(&$2); }
35741edb306SCy Schubert 	| IL_UDPLEN token		{ set_udplen(&$2); }
35841edb306SCy Schubert 	| IL_UDPSUM token		{ set_udpsum(&$2); }
35941edb306SCy Schubert 	;
36041edb306SCy Schubert 
36141edb306SCy Schubert icmp:	IL_ICMP				{ new_icmpheader(); }
36241edb306SCy Schubert 	;
36341edb306SCy Schubert 
36441edb306SCy Schubert icmpline:
36541edb306SCy Schubert 	'{' icmpbody '}' ';'		{ end_icmp(); }
36641edb306SCy Schubert 	;
36741edb306SCy Schubert 
36841edb306SCy Schubert icmpbody:
36941edb306SCy Schubert 	icmpheader
37041edb306SCy Schubert 	| icmpheader bodyline
37141edb306SCy Schubert 	;
37241edb306SCy Schubert 
37341edb306SCy Schubert icmpheader:
37441edb306SCy Schubert 	IL_ICMPTYPE icmptype
37541edb306SCy Schubert 	| IL_ICMPTYPE icmptype icmpcode
37641edb306SCy Schubert 	;
37741edb306SCy Schubert 
37841edb306SCy Schubert icmpcode:
37941edb306SCy Schubert 	IL_ICMPCODE token		{ set_icmpcodetok(&$2); }
38041edb306SCy Schubert 	;
38141edb306SCy Schubert 
38241edb306SCy Schubert icmptype:
38341edb306SCy Schubert 	IL_ICMP_ECHOREPLY ';'		{ set_icmptype(ICMP_ECHOREPLY); }
38441edb306SCy Schubert 	| IL_ICMP_ECHOREPLY '{' icmpechoopts '}' ';'
38541edb306SCy Schubert 	| unreach
38641edb306SCy Schubert 	| IL_ICMP_SOURCEQUENCH ';'	{ set_icmptype(ICMP_SOURCEQUENCH); }
38741edb306SCy Schubert 	| redirect
38841edb306SCy Schubert 	| IL_ICMP_ROUTERADVERT ';'	{ set_icmptype(ICMP_ROUTERADVERT); }
38941edb306SCy Schubert 	| IL_ICMP_ROUTERSOLICIT ';'	{ set_icmptype(ICMP_ROUTERSOLICIT); }
39041edb306SCy Schubert 	| IL_ICMP_ECHO ';'		{ set_icmptype(ICMP_ECHO); }
39141edb306SCy Schubert 	| IL_ICMP_ECHO '{' icmpechoopts '}' ';'
39241edb306SCy Schubert 	| IL_ICMP_TIMXCEED ';'		{ set_icmptype(ICMP_TIMXCEED); }
39341edb306SCy Schubert 	| IL_ICMP_TIMXCEED '{' exceed '}' ';'
39441edb306SCy Schubert 	| IL_ICMP_TSTAMP ';'		{ set_icmptype(ICMP_TSTAMP); }
39541edb306SCy Schubert 	| IL_ICMP_TSTAMPREPLY ';'	{ set_icmptype(ICMP_TSTAMPREPLY); }
39641edb306SCy Schubert 	| IL_ICMP_TSTAMPREPLY '{' icmptsopts '}' ';'
39741edb306SCy Schubert 	| IL_ICMP_IREQ ';'		{ set_icmptype(ICMP_IREQ); }
39841edb306SCy Schubert 	| IL_ICMP_IREQREPLY ';'		{ set_icmptype(ICMP_IREQREPLY); }
39941edb306SCy Schubert 	| IL_ICMP_IREQREPLY '{' data dataline '}' ';'
40041edb306SCy Schubert 	| IL_ICMP_MASKREQ ';'		{ set_icmptype(ICMP_MASKREQ); }
40141edb306SCy Schubert 	| IL_ICMP_MASKREPLY ';'		{ set_icmptype(ICMP_MASKREPLY); }
40241edb306SCy Schubert 	| IL_ICMP_MASKREPLY '{' token '}' ';'
40341edb306SCy Schubert 	| IL_ICMP_PARAMPROB ';'		{ set_icmptype(ICMP_PARAMPROB); }
40441edb306SCy Schubert 	| IL_ICMP_PARAMPROB '{' paramprob '}' ';'
40541edb306SCy Schubert 	| IL_TOKEN ';'			{ set_icmptypetok(&$1); }
40641edb306SCy Schubert 	;
40741edb306SCy Schubert 
40841edb306SCy Schubert icmpechoopts:
40941edb306SCy Schubert 	| icmpechoopts icmpecho
41041edb306SCy Schubert 	;
41141edb306SCy Schubert 
41241edb306SCy Schubert icmpecho:
41341edb306SCy Schubert 	IL_ICMP_SEQ number 		{ set_icmpseq($2); }
41441edb306SCy Schubert 	| IL_ICMP_ID number		{ set_icmpid($2); }
41541edb306SCy Schubert 	;
41641edb306SCy Schubert 
41741edb306SCy Schubert icmptsopts:
41841edb306SCy Schubert 	| icmptsopts icmpts ';'
41941edb306SCy Schubert 	;
42041edb306SCy Schubert 
42141edb306SCy Schubert icmpts: IL_ICMP_OTIME number 		{ set_icmpotime($2); }
42241edb306SCy Schubert 	| IL_ICMP_RTIME number 		{ set_icmprtime($2); }
42341edb306SCy Schubert 	| IL_ICMP_TTIME number 		{ set_icmpttime($2); }
42441edb306SCy Schubert 	;
42541edb306SCy Schubert 
42641edb306SCy Schubert unreach:
42741edb306SCy Schubert 	IL_ICMP_UNREACH
42841edb306SCy Schubert 	| IL_ICMP_UNREACH '{' unreachopts '}' ';'
42941edb306SCy Schubert 	;
43041edb306SCy Schubert 
43141edb306SCy Schubert unreachopts:
43241edb306SCy Schubert 	IL_ICMP_UNREACH_NET line
43341edb306SCy Schubert 	| IL_ICMP_UNREACH_HOST line
43441edb306SCy Schubert 	| IL_ICMP_UNREACH_PROTOCOL line
43541edb306SCy Schubert 	| IL_ICMP_UNREACH_PORT line
43641edb306SCy Schubert 	| IL_ICMP_UNREACH_NEEDFRAG number ';'	{ set_icmpmtu($2); }
43741edb306SCy Schubert 	| IL_ICMP_UNREACH_SRCFAIL line
43841edb306SCy Schubert 	| IL_ICMP_UNREACH_NET_UNKNOWN line
43941edb306SCy Schubert 	| IL_ICMP_UNREACH_HOST_UNKNOWN line
44041edb306SCy Schubert 	| IL_ICMP_UNREACH_ISOLATED line
44141edb306SCy Schubert 	| IL_ICMP_UNREACH_NET_PROHIB line
44241edb306SCy Schubert 	| IL_ICMP_UNREACH_HOST_PROHIB line
44341edb306SCy Schubert 	| IL_ICMP_UNREACH_TOSNET line
44441edb306SCy Schubert 	| IL_ICMP_UNREACH_TOSHOST line
44541edb306SCy Schubert 	| IL_ICMP_UNREACH_FILTER_PROHIB line
44641edb306SCy Schubert 	| IL_ICMP_UNREACH_HOST_PRECEDENCE line
44741edb306SCy Schubert 	| IL_ICMP_UNREACH_PRECEDENCE_CUTOFF line
44841edb306SCy Schubert 	;
44941edb306SCy Schubert 
45041edb306SCy Schubert redirect:
45141edb306SCy Schubert 	IL_ICMP_REDIRECT
45241edb306SCy Schubert 	| IL_ICMP_REDIRECT '{' redirectopts '}' ';'
45341edb306SCy Schubert 	;
45441edb306SCy Schubert 
45541edb306SCy Schubert redirectopts:
45641edb306SCy Schubert 	| IL_ICMP_REDIRECT_NET token		{ set_redir(0, &$2); }
45741edb306SCy Schubert 	| IL_ICMP_REDIRECT_HOST token		{ set_redir(1, &$2); }
45841edb306SCy Schubert 	| IL_ICMP_REDIRECT_TOSNET token		{ set_redir(2, &$2); }
45941edb306SCy Schubert 	| IL_ICMP_REDIRECT_TOSHOST token	{ set_redir(3, &$2); }
46041edb306SCy Schubert 	;
46141edb306SCy Schubert 
46241edb306SCy Schubert exceed:
46341edb306SCy Schubert 	IL_ICMP_TIMXCEED_INTRANS line
46441edb306SCy Schubert 	| IL_ICMP_TIMXCEED_REASS line
46541edb306SCy Schubert 	;
46641edb306SCy Schubert 
46741edb306SCy Schubert paramprob:
46841edb306SCy Schubert 	IL_ICMP_PARAMPROB_OPTABSENT
46941edb306SCy Schubert 	| IL_ICMP_PARAMPROB_OPTABSENT paraprobarg
47041edb306SCy Schubert 
47141edb306SCy Schubert paraprobarg:
47241edb306SCy Schubert 	'{' number '}' ';'		{ set_icmppprob($2); }
47341edb306SCy Schubert 	;
47441edb306SCy Schubert 
47541edb306SCy Schubert ipv4opt:	IL_V4OPT		{ new_ipv4opt(); }
47641edb306SCy Schubert 	;
47741edb306SCy Schubert 
47841edb306SCy Schubert ipv4optlist:
47941edb306SCy Schubert 	| ipv4opts ipv4optlist
48041edb306SCy Schubert 	;
48141edb306SCy Schubert 
48241edb306SCy Schubert ipv4opts:
48341edb306SCy Schubert 	IL_IPO_NOP ';'			{ add_ipopt(IL_IPO_NOP, NULL); }
48441edb306SCy Schubert 	| IL_IPO_RR optnumber		{ add_ipopt(IL_IPO_RR, &$2); }
48541edb306SCy Schubert 	| IL_IPO_ZSU ';'		{ add_ipopt(IL_IPO_ZSU, NULL); }
48641edb306SCy Schubert 	| IL_IPO_MTUP ';'		{ add_ipopt(IL_IPO_MTUP, NULL); }
48741edb306SCy Schubert 	| IL_IPO_MTUR ';'		{ add_ipopt(IL_IPO_MTUR, NULL); }
48841edb306SCy Schubert 	| IL_IPO_ENCODE ';'		{ add_ipopt(IL_IPO_ENCODE, NULL); }
48941edb306SCy Schubert 	| IL_IPO_TS ';'			{ add_ipopt(IL_IPO_TS, NULL); }
49041edb306SCy Schubert 	| IL_IPO_TR ';'			{ add_ipopt(IL_IPO_TR, NULL); }
49141edb306SCy Schubert 	| IL_IPO_SEC ';'		{ add_ipopt(IL_IPO_SEC, NULL); }
49241edb306SCy Schubert 	| IL_IPO_SECCLASS secclass	{ add_ipopt(IL_IPO_SECCLASS, sclass); }
49341edb306SCy Schubert 	| IL_IPO_LSRR token		{ add_ipopt(IL_IPO_LSRR,&$2); }
49441edb306SCy Schubert 	| IL_IPO_ESEC ';'		{ add_ipopt(IL_IPO_ESEC, NULL); }
49541edb306SCy Schubert 	| IL_IPO_CIPSO ';'		{ add_ipopt(IL_IPO_CIPSO, NULL); }
49641edb306SCy Schubert 	| IL_IPO_SATID optnumber	{ add_ipopt(IL_IPO_SATID,&$2);}
49741edb306SCy Schubert 	| IL_IPO_SSRR token		{ add_ipopt(IL_IPO_SSRR,&$2); }
49841edb306SCy Schubert 	| IL_IPO_ADDEXT ';'		{ add_ipopt(IL_IPO_ADDEXT, NULL); }
49941edb306SCy Schubert 	| IL_IPO_VISA ';'		{ add_ipopt(IL_IPO_VISA, NULL); }
50041edb306SCy Schubert 	| IL_IPO_IMITD ';'		{ add_ipopt(IL_IPO_IMITD, NULL); }
50141edb306SCy Schubert 	| IL_IPO_EIP ';'		{ add_ipopt(IL_IPO_EIP, NULL); }
50241edb306SCy Schubert 	| IL_IPO_FINN ';'		{ add_ipopt(IL_IPO_FINN, NULL); }
50341edb306SCy Schubert 	;
50441edb306SCy Schubert 
50541edb306SCy Schubert secclass:
50641edb306SCy Schubert 	IL_IPS_RESERV4 ';'		{ set_secclass(&$1); }
50741edb306SCy Schubert 	| IL_IPS_TOPSECRET ';'		{ set_secclass(&$1); }
50841edb306SCy Schubert 	| IL_IPS_SECRET ';'		{ set_secclass(&$1); }
50941edb306SCy Schubert 	| IL_IPS_RESERV3 ';'		{ set_secclass(&$1); }
51041edb306SCy Schubert 	| IL_IPS_CONFID ';'		{ set_secclass(&$1); }
51141edb306SCy Schubert 	| IL_IPS_UNCLASS ';'		{ set_secclass(&$1); }
51241edb306SCy Schubert 	| IL_IPS_RESERV2 ';'		{ set_secclass(&$1); }
51341edb306SCy Schubert 	| IL_IPS_RESERV1 ';'		{ set_secclass(&$1); }
51441edb306SCy Schubert 	;
51541edb306SCy Schubert 
51641edb306SCy Schubert data:	IL_DATA				{ new_data(); }
51741edb306SCy Schubert 	;
51841edb306SCy Schubert 
51941edb306SCy Schubert dataline:
52041edb306SCy Schubert 	'{' databody '}' ';'		{ end_data(); }
52141edb306SCy Schubert 	;
52241edb306SCy Schubert 
52341edb306SCy Schubert databody: dataopts
52441edb306SCy Schubert 	| dataopts databody
52541edb306SCy Schubert 	;
52641edb306SCy Schubert 
52741edb306SCy Schubert dataopts:
52841edb306SCy Schubert 	IL_DLEN token			{ set_datalen(&$2); }
52941edb306SCy Schubert 	| IL_DVALUE token 		{ set_data(&$2); }
53041edb306SCy Schubert 	| IL_DFILE token 		{ set_datafile(&$2); }
53141edb306SCy Schubert 	;
53241edb306SCy Schubert 
53341edb306SCy Schubert token: IL_TOKEN ';'
53441edb306SCy Schubert 	;
53541edb306SCy Schubert 
53641edb306SCy Schubert optoken: ';'				{ $$ = ""; }
53741edb306SCy Schubert 	| token
53841edb306SCy Schubert 	;
53941edb306SCy Schubert 
54041edb306SCy Schubert number: digits ';'
54141edb306SCy Schubert 	;
54241edb306SCy Schubert 
54341edb306SCy Schubert optnumber: ';'				{ $$ = 0; }
54441edb306SCy Schubert 	| number
54541edb306SCy Schubert 	;
54641edb306SCy Schubert 
54741edb306SCy Schubert digits:	IL_NUMBER
54841edb306SCy Schubert 	| digits IL_NUMBER
54941edb306SCy Schubert 	;
55041edb306SCy Schubert %%
55141edb306SCy Schubert 
55241edb306SCy Schubert struct	statetoopt	toipopts[] = {
55341edb306SCy Schubert 	{ IL_IPO_NOP,		IPOPT_NOP },
55441edb306SCy Schubert 	{ IL_IPO_RR,		IPOPT_RR },
55541edb306SCy Schubert 	{ IL_IPO_ZSU,		IPOPT_ZSU },
55641edb306SCy Schubert 	{ IL_IPO_MTUP,		IPOPT_MTUP },
55741edb306SCy Schubert 	{ IL_IPO_MTUR,		IPOPT_MTUR },
55841edb306SCy Schubert 	{ IL_IPO_ENCODE,	IPOPT_ENCODE },
55941edb306SCy Schubert 	{ IL_IPO_TS,		IPOPT_TS },
56041edb306SCy Schubert 	{ IL_IPO_TR,		IPOPT_TR },
56141edb306SCy Schubert 	{ IL_IPO_SEC,		IPOPT_SECURITY },
56241edb306SCy Schubert 	{ IL_IPO_SECCLASS,	IPOPT_SECURITY },
56341edb306SCy Schubert 	{ IL_IPO_LSRR,		IPOPT_LSRR },
56441edb306SCy Schubert 	{ IL_IPO_ESEC,		IPOPT_E_SEC },
56541edb306SCy Schubert 	{ IL_IPO_CIPSO,		IPOPT_CIPSO },
56641edb306SCy Schubert 	{ IL_IPO_SATID,		IPOPT_SATID },
56741edb306SCy Schubert 	{ IL_IPO_SSRR,		IPOPT_SSRR },
56841edb306SCy Schubert 	{ IL_IPO_ADDEXT,	IPOPT_ADDEXT },
56941edb306SCy Schubert 	{ IL_IPO_VISA,		IPOPT_VISA },
57041edb306SCy Schubert 	{ IL_IPO_IMITD,		IPOPT_IMITD },
57141edb306SCy Schubert 	{ IL_IPO_EIP,		IPOPT_EIP },
57241edb306SCy Schubert 	{ IL_IPO_FINN,		IPOPT_FINN },
57341edb306SCy Schubert 	{ 0, 0 }
57441edb306SCy Schubert };
57541edb306SCy Schubert 
57641edb306SCy Schubert struct	statetoopt	tosecopts[] = {
57741edb306SCy Schubert 	{ IL_IPS_RESERV4,	IPSO_CLASS_RES4 },
57841edb306SCy Schubert 	{ IL_IPS_TOPSECRET,	IPSO_CLASS_TOPS },
57941edb306SCy Schubert 	{ IL_IPS_SECRET,	IPSO_CLASS_SECR },
58041edb306SCy Schubert 	{ IL_IPS_RESERV3,	IPSO_CLASS_RES3 },
58141edb306SCy Schubert 	{ IL_IPS_CONFID,	IPSO_CLASS_CONF },
58241edb306SCy Schubert 	{ IL_IPS_UNCLASS,	IPSO_CLASS_UNCL },
58341edb306SCy Schubert 	{ IL_IPS_RESERV2,	IPSO_CLASS_RES2 },
58441edb306SCy Schubert 	{ IL_IPS_RESERV1,	IPSO_CLASS_RES1 },
58541edb306SCy Schubert 	{ 0, 0 }
58641edb306SCy Schubert };
58741edb306SCy Schubert 
58841edb306SCy Schubert 
getipv4addr(arg)58941edb306SCy Schubert struct in_addr getipv4addr(arg)
59041edb306SCy Schubert char *arg;
59141edb306SCy Schubert {
59241edb306SCy Schubert 	struct hostent *hp;
59341edb306SCy Schubert 	struct in_addr in;
59441edb306SCy Schubert 
59541edb306SCy Schubert 	in.s_addr = 0xffffffff;
59641edb306SCy Schubert 
59741edb306SCy Schubert 	if ((hp = gethostbyname(arg)))
59841edb306SCy Schubert 		bcopy(hp->h_addr, &in.s_addr, sizeof(struct in_addr));
59941edb306SCy Schubert 	else
60041edb306SCy Schubert 		in.s_addr = inet_addr(arg);
6012582ae57SCy Schubert 	return(in);
60241edb306SCy Schubert }
60341edb306SCy Schubert 
60441edb306SCy Schubert 
getportnum(pr,name)60541edb306SCy Schubert u_short getportnum(pr, name)
60641edb306SCy Schubert char *pr, *name;
60741edb306SCy Schubert {
60841edb306SCy Schubert 	struct servent *sp;
60941edb306SCy Schubert 
61041edb306SCy Schubert 	if (!(sp = getservbyname(name, pr)))
6112582ae57SCy Schubert 		return(htons(atoi(name)));
6122582ae57SCy Schubert 	return(sp->s_port);
61341edb306SCy Schubert }
61441edb306SCy Schubert 
61541edb306SCy Schubert 
geteaddr(char * arg,struct ether_addr * buf)616efeb8bffSCy Schubert struct ether_addr *geteaddr(char *arg, struct ether_addr *buf)
61741edb306SCy Schubert {
61841edb306SCy Schubert 	struct ether_addr *e;
61941edb306SCy Schubert 
62041edb306SCy Schubert 	e = ether_aton(arg);
62141edb306SCy Schubert 	if (!e)
62241edb306SCy Schubert 		fprintf(stderr, "Invalid ethernet address: %s\n", arg);
62341edb306SCy Schubert 	else
62441edb306SCy Schubert # ifdef	__FreeBSD__
62541edb306SCy Schubert 		bcopy(e->octet, buf->octet, sizeof(e->octet));
62641edb306SCy Schubert # else
62741edb306SCy Schubert 		bcopy(e->ether_addr_octet, buf->ether_addr_octet,
62841edb306SCy Schubert 		      sizeof(e->ether_addr_octet));
62941edb306SCy Schubert # endif
6302582ae57SCy Schubert 	return(e);
63141edb306SCy Schubert }
63241edb306SCy Schubert 
63341edb306SCy Schubert 
new_header(int type)634efeb8bffSCy Schubert void *new_header(int type)
63541edb306SCy Schubert {
63641edb306SCy Schubert 	aniphdr_t *aip, *oip = canip;
63741edb306SCy Schubert 	int	sz = 0;
63841edb306SCy Schubert 
63941edb306SCy Schubert 	aip = (aniphdr_t *)calloc(1, sizeof(*aip));
64041edb306SCy Schubert 	*aniptail = aip;
64141edb306SCy Schubert 	aniptail = &aip->ah_next;
64241edb306SCy Schubert 	aip->ah_p = type;
64341edb306SCy Schubert 	aip->ah_prev = oip;
64441edb306SCy Schubert 	canip = aip;
64541edb306SCy Schubert 
64641edb306SCy Schubert 	if (type == IPPROTO_UDP)
64741edb306SCy Schubert 		sz = sizeof(udphdr_t);
64841edb306SCy Schubert 	else if (type == IPPROTO_TCP)
64941edb306SCy Schubert 		sz = sizeof(tcphdr_t);
65041edb306SCy Schubert 	else if (type == IPPROTO_ICMP)
65141edb306SCy Schubert 		sz = sizeof(icmphdr_t);
65241edb306SCy Schubert 	else if (type == IPPROTO_IP)
65341edb306SCy Schubert 		sz = sizeof(ip_t);
65441edb306SCy Schubert 
65541edb306SCy Schubert 	if (oip)
65641edb306SCy Schubert 		canip->ah_data = oip->ah_data + oip->ah_len;
65741edb306SCy Schubert 	else
65841edb306SCy Schubert 		canip->ah_data = (char *)ipbuffer;
65941edb306SCy Schubert 
66041edb306SCy Schubert 	/*
66141edb306SCy Schubert 	 * Increase the size fields in all wrapping headers.
66241edb306SCy Schubert 	 */
66341edb306SCy Schubert 	for (aip = aniphead; aip; aip = aip->ah_next) {
66441edb306SCy Schubert 		aip->ah_len += sz;
66541edb306SCy Schubert 		if (aip->ah_p == IPPROTO_IP)
66641edb306SCy Schubert 			aip->ah_ip->ip_len += sz;
66741edb306SCy Schubert 		else if (aip->ah_p == IPPROTO_UDP)
66841edb306SCy Schubert 			aip->ah_udp->uh_ulen += sz;
66941edb306SCy Schubert 	}
67041edb306SCy Schubert 	return(void *)canip->ah_data;
67141edb306SCy Schubert }
67241edb306SCy Schubert 
67341edb306SCy Schubert 
free_aniplist(void)674efeb8bffSCy Schubert void free_aniplist(void)
67541edb306SCy Schubert {
67641edb306SCy Schubert 	aniphdr_t *aip, **aipp = &aniphead;
67741edb306SCy Schubert 
67841edb306SCy Schubert 	while ((aip = *aipp)) {
67941edb306SCy Schubert 		*aipp = aip->ah_next;
68041edb306SCy Schubert 		free(aip);
68141edb306SCy Schubert 	}
68241edb306SCy Schubert 	aniptail = &aniphead;
68341edb306SCy Schubert }
68441edb306SCy Schubert 
68541edb306SCy Schubert 
inc_anipheaders(int inc)686efeb8bffSCy Schubert void inc_anipheaders(int inc)
68741edb306SCy Schubert {
68841edb306SCy Schubert 	aniphdr_t *aip;
68941edb306SCy Schubert 
69041edb306SCy Schubert 	for (aip = aniphead; aip; aip = aip->ah_next) {
69141edb306SCy Schubert 		aip->ah_len += inc;
69241edb306SCy Schubert 		if (aip->ah_p == IPPROTO_IP)
69341edb306SCy Schubert 			aip->ah_ip->ip_len += inc;
69441edb306SCy Schubert 		else if (aip->ah_p == IPPROTO_UDP)
69541edb306SCy Schubert 			aip->ah_udp->uh_ulen += inc;
69641edb306SCy Schubert 	}
69741edb306SCy Schubert }
69841edb306SCy Schubert 
69941edb306SCy Schubert 
new_data(void)700efeb8bffSCy Schubert void new_data(void)
70141edb306SCy Schubert {
70241edb306SCy Schubert 	(void) new_header(-1);
70341edb306SCy Schubert 	canip->ah_len = 0;
70441edb306SCy Schubert }
70541edb306SCy Schubert 
70641edb306SCy Schubert 
set_datalen(char ** arg)707efeb8bffSCy Schubert void set_datalen(char **arg)
70841edb306SCy Schubert {
70941edb306SCy Schubert 	int	len;
71041edb306SCy Schubert 
71141edb306SCy Schubert 	len = strtol(*arg, NULL, 0);
71241edb306SCy Schubert 	inc_anipheaders(len);
71341edb306SCy Schubert 	free(*arg);
71441edb306SCy Schubert 	*arg = NULL;
71541edb306SCy Schubert }
71641edb306SCy Schubert 
71741edb306SCy Schubert 
set_data(char ** arg)718efeb8bffSCy Schubert void set_data(char **arg)
71941edb306SCy Schubert {
72041edb306SCy Schubert 	u_char *s = (u_char *)*arg, *t = (u_char *)canip->ah_data, c;
72141edb306SCy Schubert 	int len = 0, todo = 0, quote = 0, val = 0;
72241edb306SCy Schubert 
72341edb306SCy Schubert 	while ((c = *s++)) {
72441edb306SCy Schubert 		if (todo) {
72541edb306SCy Schubert 			if (ISDIGIT(c)) {
72641edb306SCy Schubert 				todo--;
72741edb306SCy Schubert 				if (c > '7') {
72841edb306SCy Schubert 					fprintf(stderr, "octal with %c!\n", c);
72941edb306SCy Schubert 					break;
73041edb306SCy Schubert 				}
73141edb306SCy Schubert 				val <<= 3;
73241edb306SCy Schubert 				val |= (c - '0');
73341edb306SCy Schubert 			}
73441edb306SCy Schubert 			if (!ISDIGIT(c) || !todo) {
73541edb306SCy Schubert 				*t++ = (u_char)(val & 0xff);
73641edb306SCy Schubert 				todo = 0;
73741edb306SCy Schubert 			}
73841edb306SCy Schubert 			if (todo)
73941edb306SCy Schubert 				continue;
74041edb306SCy Schubert 		}
74141edb306SCy Schubert 		if (quote) {
74241edb306SCy Schubert 			if (ISDIGIT(c)) {
74341edb306SCy Schubert 				todo = 2;
74441edb306SCy Schubert 				if (c > '7') {
74541edb306SCy Schubert 					fprintf(stderr, "octal with %c!\n", c);
74641edb306SCy Schubert 					break;
74741edb306SCy Schubert 				}
74841edb306SCy Schubert 				val = (c - '0');
74941edb306SCy Schubert 			} else {
75041edb306SCy Schubert 				switch (c)
75141edb306SCy Schubert 				{
75241edb306SCy Schubert 				case '\"' :
75341edb306SCy Schubert 					*t++ = '\"';
75441edb306SCy Schubert 					break;
75541edb306SCy Schubert 				case '\\' :
75641edb306SCy Schubert 					*t++ = '\\';
75741edb306SCy Schubert 					break;
75841edb306SCy Schubert 				case 'n' :
75941edb306SCy Schubert 					*t++ = '\n';
76041edb306SCy Schubert 					break;
76141edb306SCy Schubert 				case 'r' :
76241edb306SCy Schubert 					*t++ = '\r';
76341edb306SCy Schubert 					break;
76441edb306SCy Schubert 				case 't' :
76541edb306SCy Schubert 					*t++ = '\t';
76641edb306SCy Schubert 					break;
76741edb306SCy Schubert 				}
76841edb306SCy Schubert 			}
76941edb306SCy Schubert 			quote = 0;
77041edb306SCy Schubert 			continue;
77141edb306SCy Schubert 		}
77241edb306SCy Schubert 
77341edb306SCy Schubert 		if (c == '\\')
77441edb306SCy Schubert 			quote = 1;
77541edb306SCy Schubert 		else
77641edb306SCy Schubert 			*t++ = c;
77741edb306SCy Schubert 	}
77841edb306SCy Schubert 	if (todo)
77941edb306SCy Schubert 		*t++ = (u_char)(val & 0xff);
78041edb306SCy Schubert 	if (quote)
78141edb306SCy Schubert 		*t++ = '\\';
78241edb306SCy Schubert 	len = t - (u_char *)canip->ah_data;
78341edb306SCy Schubert 	inc_anipheaders(len - canip->ah_len);
78441edb306SCy Schubert 	canip->ah_len = len;
78541edb306SCy Schubert }
78641edb306SCy Schubert 
78741edb306SCy Schubert 
set_datafile(char ** arg)788efeb8bffSCy Schubert void set_datafile(char **arg)
78941edb306SCy Schubert {
79041edb306SCy Schubert 	struct stat sb;
79141edb306SCy Schubert 	char *file = *arg;
79241edb306SCy Schubert 	int fd, len;
79341edb306SCy Schubert 
79441edb306SCy Schubert 	if ((fd = open(file, O_RDONLY)) == -1) {
79541edb306SCy Schubert 		perror("open");
79641edb306SCy Schubert 		exit(-1);
79741edb306SCy Schubert 	}
79841edb306SCy Schubert 
79941edb306SCy Schubert 	if (fstat(fd, &sb) == -1) {
80041edb306SCy Schubert 		perror("fstat");
80141edb306SCy Schubert 		exit(-1);
80241edb306SCy Schubert 	}
80341edb306SCy Schubert 
80441edb306SCy Schubert 	if ((sb.st_size + aniphead->ah_len ) > 65535) {
80541edb306SCy Schubert 		fprintf(stderr, "data file %s too big to include.\n", file);
80641edb306SCy Schubert 		close(fd);
80741edb306SCy Schubert 		return;
80841edb306SCy Schubert 	}
80941edb306SCy Schubert 	if ((len = read(fd, canip->ah_data, sb.st_size)) == -1) {
81041edb306SCy Schubert 		perror("read");
81141edb306SCy Schubert 		close(fd);
81241edb306SCy Schubert 		return;
81341edb306SCy Schubert 	}
81441edb306SCy Schubert 	inc_anipheaders(len);
81541edb306SCy Schubert 	canip->ah_len += len;
81641edb306SCy Schubert 	close(fd);
81741edb306SCy Schubert }
81841edb306SCy Schubert 
81941edb306SCy Schubert 
new_packet(void)820efeb8bffSCy Schubert void new_packet(void)
82141edb306SCy Schubert {
82241edb306SCy Schubert 	static	u_short	id = 0;
82341edb306SCy Schubert 
82441edb306SCy Schubert 	if (!aniphead)
82541edb306SCy Schubert 		bzero((char *)ipbuffer, sizeof(ipbuffer));
82641edb306SCy Schubert 
82741edb306SCy Schubert 	ip = (ip_t *)new_header(IPPROTO_IP);
82841edb306SCy Schubert 	ip->ip_v = IPVERSION;
82941edb306SCy Schubert 	ip->ip_hl = sizeof(ip_t) >> 2;
83041edb306SCy Schubert 	ip->ip_len = sizeof(ip_t);
83141edb306SCy Schubert 	ip->ip_ttl = 63;
83241edb306SCy Schubert 	ip->ip_id = htons(id++);
83341edb306SCy Schubert }
83441edb306SCy Schubert 
83541edb306SCy Schubert 
set_ipv4proto(arg)83641edb306SCy Schubert void set_ipv4proto(arg)
83741edb306SCy Schubert char **arg;
83841edb306SCy Schubert {
83941edb306SCy Schubert 	struct protoent *pr;
84041edb306SCy Schubert 
84141edb306SCy Schubert 	if ((pr = getprotobyname(*arg)))
84241edb306SCy Schubert 		ip->ip_p = pr->p_proto;
84341edb306SCy Schubert 	else
84441edb306SCy Schubert 		if (!(ip->ip_p = atoi(*arg)))
84541edb306SCy Schubert 			fprintf(stderr, "unknown protocol %s\n", *arg);
84641edb306SCy Schubert 	free(*arg);
84741edb306SCy Schubert 	*arg = NULL;
84841edb306SCy Schubert }
84941edb306SCy Schubert 
85041edb306SCy Schubert 
set_ipv4src(char ** arg)851efeb8bffSCy Schubert void set_ipv4src(char **arg)
85241edb306SCy Schubert {
85341edb306SCy Schubert 	ip->ip_src = getipv4addr(*arg);
85441edb306SCy Schubert 	free(*arg);
85541edb306SCy Schubert 	*arg = NULL;
85641edb306SCy Schubert }
85741edb306SCy Schubert 
85841edb306SCy Schubert 
set_ipv4dst(char ** arg)859efeb8bffSCy Schubert void set_ipv4dst(char **arg)
86041edb306SCy Schubert {
86141edb306SCy Schubert 	ip->ip_dst = getipv4addr(*arg);
86241edb306SCy Schubert 	free(*arg);
86341edb306SCy Schubert 	*arg = NULL;
86441edb306SCy Schubert }
86541edb306SCy Schubert 
86641edb306SCy Schubert 
set_ipv4off(char ** arg)867efeb8bffSCy Schubert void set_ipv4off(char **arg)
86841edb306SCy Schubert {
86941edb306SCy Schubert 	ip->ip_off = htons(strtol(*arg, NULL, 0));
87041edb306SCy Schubert 	free(*arg);
87141edb306SCy Schubert 	*arg = NULL;
87241edb306SCy Schubert }
87341edb306SCy Schubert 
87441edb306SCy Schubert 
set_ipv4v(char ** arg)875efeb8bffSCy Schubert void set_ipv4v(char **arg)
87641edb306SCy Schubert {
87741edb306SCy Schubert 	ip->ip_v = strtol(*arg, NULL, 0);
87841edb306SCy Schubert 	free(*arg);
87941edb306SCy Schubert 	*arg = NULL;
88041edb306SCy Schubert }
88141edb306SCy Schubert 
88241edb306SCy Schubert 
set_ipv4hl(char ** arg)883efeb8bffSCy Schubert void set_ipv4hl(char **arg)
88441edb306SCy Schubert {
88541edb306SCy Schubert 	int newhl, inc;
88641edb306SCy Schubert 
88741edb306SCy Schubert 	newhl = strtol(*arg, NULL, 0);
88841edb306SCy Schubert 	inc = (newhl - ip->ip_hl) << 2;
88941edb306SCy Schubert 	ip->ip_len += inc;
89041edb306SCy Schubert 	ip->ip_hl = newhl;
89141edb306SCy Schubert 	canip->ah_len += inc;
89241edb306SCy Schubert 	free(*arg);
89341edb306SCy Schubert 	*arg = NULL;
89441edb306SCy Schubert }
89541edb306SCy Schubert 
89641edb306SCy Schubert 
set_ipv4ttl(char ** arg)897efeb8bffSCy Schubert void set_ipv4ttl(char **arg)
89841edb306SCy Schubert {
89941edb306SCy Schubert 	ip->ip_ttl = strtol(*arg, NULL, 0);
90041edb306SCy Schubert 	free(*arg);
90141edb306SCy Schubert 	*arg = NULL;
90241edb306SCy Schubert }
90341edb306SCy Schubert 
90441edb306SCy Schubert 
set_ipv4tos(char ** arg)905efeb8bffSCy Schubert void set_ipv4tos(char **arg)
90641edb306SCy Schubert {
90741edb306SCy Schubert 	ip->ip_tos = strtol(*arg, NULL, 0);
90841edb306SCy Schubert 	free(*arg);
90941edb306SCy Schubert 	*arg = NULL;
91041edb306SCy Schubert }
91141edb306SCy Schubert 
91241edb306SCy Schubert 
set_ipv4id(char ** arg)913efeb8bffSCy Schubert void set_ipv4id(char **arg)
91441edb306SCy Schubert {
91541edb306SCy Schubert 	ip->ip_id = htons(strtol(*arg, NULL, 0));
91641edb306SCy Schubert 	free(*arg);
91741edb306SCy Schubert 	*arg = NULL;
91841edb306SCy Schubert }
91941edb306SCy Schubert 
92041edb306SCy Schubert 
set_ipv4sum(char ** arg)921efeb8bffSCy Schubert void set_ipv4sum(char **arg)
92241edb306SCy Schubert {
92341edb306SCy Schubert 	ip->ip_sum = strtol(*arg, NULL, 0);
92441edb306SCy Schubert 	free(*arg);
92541edb306SCy Schubert 	*arg = NULL;
92641edb306SCy Schubert }
92741edb306SCy Schubert 
92841edb306SCy Schubert 
set_ipv4len(char ** arg)929efeb8bffSCy Schubert void set_ipv4len(char **arg)
93041edb306SCy Schubert {
93141edb306SCy Schubert 	int len;
93241edb306SCy Schubert 
93341edb306SCy Schubert 	len = strtol(*arg, NULL, 0);
93441edb306SCy Schubert 	inc_anipheaders(len - ip->ip_len);
93541edb306SCy Schubert 	ip->ip_len = len;
93641edb306SCy Schubert 	free(*arg);
93741edb306SCy Schubert 	*arg = NULL;
93841edb306SCy Schubert }
93941edb306SCy Schubert 
94041edb306SCy Schubert 
new_tcpheader(void)941efeb8bffSCy Schubert void new_tcpheader(void)
94241edb306SCy Schubert {
94341edb306SCy Schubert 
94441edb306SCy Schubert 	if ((ip->ip_p) && (ip->ip_p != IPPROTO_TCP)) {
94541edb306SCy Schubert 		fprintf(stderr, "protocol %d specified with TCP!\n", ip->ip_p);
94641edb306SCy Schubert 		return;
94741edb306SCy Schubert 	}
94841edb306SCy Schubert 	ip->ip_p = IPPROTO_TCP;
94941edb306SCy Schubert 
95041edb306SCy Schubert 	tcp = (tcphdr_t *)new_header(IPPROTO_TCP);
95141edb306SCy Schubert 	tcp->th_win = htons(4096);
95241edb306SCy Schubert 	tcp->th_off = sizeof(*tcp) >> 2;
95341edb306SCy Schubert }
95441edb306SCy Schubert 
95541edb306SCy Schubert 
set_tcpsport(char ** arg)956efeb8bffSCy Schubert void set_tcpsport(char **arg)
95741edb306SCy Schubert {
95841edb306SCy Schubert 	u_short *port;
95941edb306SCy Schubert 	char *pr;
96041edb306SCy Schubert 
96141edb306SCy Schubert 	if (ip->ip_p == IPPROTO_UDP) {
96241edb306SCy Schubert 		port = &udp->uh_sport;
96341edb306SCy Schubert 		pr = "udp";
96441edb306SCy Schubert 	} else {
96541edb306SCy Schubert 		port = &tcp->th_sport;
96641edb306SCy Schubert 		pr = "udp";
96741edb306SCy Schubert 	}
96841edb306SCy Schubert 
96941edb306SCy Schubert 	*port = getportnum(pr, *arg);
97041edb306SCy Schubert 	free(*arg);
97141edb306SCy Schubert 	*arg = NULL;
97241edb306SCy Schubert }
97341edb306SCy Schubert 
97441edb306SCy Schubert 
set_tcpdport(char ** arg)975efeb8bffSCy Schubert void set_tcpdport(char **arg)
97641edb306SCy Schubert {
97741edb306SCy Schubert 	u_short *port;
97841edb306SCy Schubert 	char *pr;
97941edb306SCy Schubert 
98041edb306SCy Schubert 	if (ip->ip_p == IPPROTO_UDP) {
98141edb306SCy Schubert 		port = &udp->uh_dport;
98241edb306SCy Schubert 		pr = "udp";
98341edb306SCy Schubert 	} else {
98441edb306SCy Schubert 		port = &tcp->th_dport;
98541edb306SCy Schubert 		pr = "udp";
98641edb306SCy Schubert 	}
98741edb306SCy Schubert 
98841edb306SCy Schubert 	*port = getportnum(pr, *arg);
98941edb306SCy Schubert 	free(*arg);
99041edb306SCy Schubert 	*arg = NULL;
99141edb306SCy Schubert }
99241edb306SCy Schubert 
99341edb306SCy Schubert 
set_tcpseq(char ** arg)994efeb8bffSCy Schubert void set_tcpseq(char **arg)
99541edb306SCy Schubert {
99641edb306SCy Schubert 	tcp->th_seq = htonl(strtol(*arg, NULL, 0));
99741edb306SCy Schubert 	free(*arg);
99841edb306SCy Schubert 	*arg = NULL;
99941edb306SCy Schubert }
100041edb306SCy Schubert 
100141edb306SCy Schubert 
set_tcpack(char ** arg)1002efeb8bffSCy Schubert void set_tcpack(char **arg)
100341edb306SCy Schubert {
100441edb306SCy Schubert 	tcp->th_ack = htonl(strtol(*arg, NULL, 0));
100541edb306SCy Schubert 	free(*arg);
100641edb306SCy Schubert 	*arg = NULL;
100741edb306SCy Schubert }
100841edb306SCy Schubert 
100941edb306SCy Schubert 
set_tcpoff(char ** arg)1010efeb8bffSCy Schubert void set_tcpoff(char **arg)
101141edb306SCy Schubert {
101241edb306SCy Schubert 	int	off;
101341edb306SCy Schubert 
101441edb306SCy Schubert 	off = strtol(*arg, NULL, 0);
101541edb306SCy Schubert 	inc_anipheaders((off - tcp->th_off) << 2);
101641edb306SCy Schubert 	tcp->th_off = off;
101741edb306SCy Schubert 	free(*arg);
101841edb306SCy Schubert 	*arg = NULL;
101941edb306SCy Schubert }
102041edb306SCy Schubert 
102141edb306SCy Schubert 
set_tcpurp(char ** arg)1022efeb8bffSCy Schubert void set_tcpurp(char **arg)
102341edb306SCy Schubert {
102441edb306SCy Schubert 	tcp->th_urp = htons(strtol(*arg, NULL, 0));
102541edb306SCy Schubert 	free(*arg);
102641edb306SCy Schubert 	*arg = NULL;
102741edb306SCy Schubert }
102841edb306SCy Schubert 
102941edb306SCy Schubert 
set_tcpwin(char ** arg)1030efeb8bffSCy Schubert void set_tcpwin(char **arg)
103141edb306SCy Schubert {
103241edb306SCy Schubert 	tcp->th_win = htons(strtol(*arg, NULL, 0));
103341edb306SCy Schubert 	free(*arg);
103441edb306SCy Schubert 	*arg = NULL;
103541edb306SCy Schubert }
103641edb306SCy Schubert 
103741edb306SCy Schubert 
set_tcpsum(char ** arg)1038efeb8bffSCy Schubert void set_tcpsum(char **arg)
103941edb306SCy Schubert {
104041edb306SCy Schubert 	tcp->th_sum = strtol(*arg, NULL, 0);
104141edb306SCy Schubert 	free(*arg);
104241edb306SCy Schubert 	*arg = NULL;
104341edb306SCy Schubert }
104441edb306SCy Schubert 
104541edb306SCy Schubert 
set_tcpflags(char ** arg)1046efeb8bffSCy Schubert void set_tcpflags(char **arg)
104741edb306SCy Schubert {
104841edb306SCy Schubert 	static	char	flags[] = "ASURPF";
104941edb306SCy Schubert 	static	int	flagv[] = { TH_ACK, TH_SYN, TH_URG, TH_RST, TH_PUSH,
105041edb306SCy Schubert 				    TH_FIN } ;
105141edb306SCy Schubert 	char *s, *t;
105241edb306SCy Schubert 
105341edb306SCy Schubert 	for (s = *arg; *s; s++)
105441edb306SCy Schubert 		if (!(t = strchr(flags, *s))) {
105541edb306SCy Schubert 			if (s - *arg) {
105641edb306SCy Schubert 				fprintf(stderr, "unknown TCP flag %c\n", *s);
105741edb306SCy Schubert 				break;
105841edb306SCy Schubert 			}
105941edb306SCy Schubert 			tcp->th_flags = strtol(*arg, NULL, 0);
106041edb306SCy Schubert 			break;
106141edb306SCy Schubert 		} else
106241edb306SCy Schubert 			tcp->th_flags |= flagv[t - flags];
106341edb306SCy Schubert 	free(*arg);
106441edb306SCy Schubert 	*arg = NULL;
106541edb306SCy Schubert }
106641edb306SCy Schubert 
106741edb306SCy Schubert 
set_tcpopt(int state,char ** arg)1068efeb8bffSCy Schubert void set_tcpopt(int state, char **arg)
106941edb306SCy Schubert {
107041edb306SCy Schubert 	u_char *s;
107141edb306SCy Schubert 	int val, len, val2, pad, optval;
107241edb306SCy Schubert 
107341edb306SCy Schubert 	if (arg && *arg)
107441edb306SCy Schubert 		val = atoi(*arg);
107541edb306SCy Schubert 	else
107641edb306SCy Schubert 		val = 0;
107741edb306SCy Schubert 
107841edb306SCy Schubert 	s = (u_char *)tcp + sizeof(*tcp) + canip->ah_optlen;
107941edb306SCy Schubert 	switch (state)
108041edb306SCy Schubert 	{
108141edb306SCy Schubert 	case IL_TCPO_EOL :
108241edb306SCy Schubert 		optval = 0;
108341edb306SCy Schubert 		len = 1;
108441edb306SCy Schubert 		break;
108541edb306SCy Schubert 	case IL_TCPO_NOP :
108641edb306SCy Schubert 		optval = 1;
108741edb306SCy Schubert 		len = 1;
108841edb306SCy Schubert 		break;
108941edb306SCy Schubert 	case IL_TCPO_MSS :
109041edb306SCy Schubert 		optval = 2;
109141edb306SCy Schubert 		len = 4;
109241edb306SCy Schubert 		break;
109341edb306SCy Schubert 	case IL_TCPO_WSCALE :
109441edb306SCy Schubert 		optval = 3;
109541edb306SCy Schubert 		len = 3;
109641edb306SCy Schubert 		break;
109741edb306SCy Schubert 	case IL_TCPO_TS :
109841edb306SCy Schubert 		optval = 8;
109941edb306SCy Schubert 		len = 10;
110041edb306SCy Schubert 		break;
110141edb306SCy Schubert 	default :
110241edb306SCy Schubert 		optval = 0;
110341edb306SCy Schubert 		len = 0;
110441edb306SCy Schubert 		break;
110541edb306SCy Schubert 	}
110641edb306SCy Schubert 
110741edb306SCy Schubert 	if (len > 1) {
110841edb306SCy Schubert 		/*
110941edb306SCy Schubert 		 * prepend padding - if required.
111041edb306SCy Schubert 		 */
111141edb306SCy Schubert 		if (len & 3)
111241edb306SCy Schubert 			for (pad = 4 - (len & 3); pad; pad--) {
111341edb306SCy Schubert 				*s++ = 1;
111441edb306SCy Schubert 				canip->ah_optlen++;
111541edb306SCy Schubert 			}
111641edb306SCy Schubert 		/*
111741edb306SCy Schubert 		 * build tcp option
111841edb306SCy Schubert 		 */
111941edb306SCy Schubert 		*s++ = (u_char)optval;
112041edb306SCy Schubert 		*s++ = (u_char)len;
112141edb306SCy Schubert 		if (len > 2) {
112241edb306SCy Schubert 			if (len == 3) {		/* 1 byte - char */
112341edb306SCy Schubert 				*s++ = (u_char)val;
112441edb306SCy Schubert 			} else if (len == 4) {	/* 2 bytes - short */
112541edb306SCy Schubert 				*s++ = (u_char)((val >> 8) & 0xff);
112641edb306SCy Schubert 				*s++ = (u_char)(val & 0xff);
112741edb306SCy Schubert 			} else if (len >= 6) {	/* 4 bytes - long */
112841edb306SCy Schubert 				val2 = htonl(val);
112941edb306SCy Schubert 				bcopy((char *)&val2, s, 4);
113041edb306SCy Schubert 			}
113141edb306SCy Schubert 			s += (len - 2);
113241edb306SCy Schubert 		}
113341edb306SCy Schubert 	} else
113441edb306SCy Schubert 		*s++ = (u_char)optval;
113541edb306SCy Schubert 
113641edb306SCy Schubert 	canip->ah_lastopt = optval;
113741edb306SCy Schubert 	canip->ah_optlen += len;
113841edb306SCy Schubert 
113941edb306SCy Schubert 	if (arg && *arg) {
114041edb306SCy Schubert 		free(*arg);
114141edb306SCy Schubert 		*arg = NULL;
114241edb306SCy Schubert 	}
114341edb306SCy Schubert }
114441edb306SCy Schubert 
114541edb306SCy Schubert 
end_tcpopt(void)1146efeb8bffSCy Schubert void end_tcpopt(void)
114741edb306SCy Schubert {
114841edb306SCy Schubert 	int pad;
114941edb306SCy Schubert 	char *s = (char *)tcp;
115041edb306SCy Schubert 
115141edb306SCy Schubert 	s += sizeof(*tcp) + canip->ah_optlen;
115241edb306SCy Schubert 	/*
115341edb306SCy Schubert 	 * pad out so that we have a multiple of 4 bytes in size fo the
115441edb306SCy Schubert 	 * options.  make sure last byte is EOL.
115541edb306SCy Schubert 	 */
115641edb306SCy Schubert 	if (canip->ah_optlen & 3) {
115741edb306SCy Schubert 		if (canip->ah_lastopt != 1) {
115841edb306SCy Schubert 			for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) {
115941edb306SCy Schubert 				*s++ = 1;
116041edb306SCy Schubert 				canip->ah_optlen++;
116141edb306SCy Schubert 			}
116241edb306SCy Schubert 			canip->ah_optlen++;
116341edb306SCy Schubert 		} else {
116441edb306SCy Schubert 			s -= 1;
116541edb306SCy Schubert 
116641edb306SCy Schubert 			for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) {
116741edb306SCy Schubert 				*s++ = 1;
116841edb306SCy Schubert 				canip->ah_optlen++;
116941edb306SCy Schubert 			}
117041edb306SCy Schubert 		}
117141edb306SCy Schubert 		*s++ = 0;
117241edb306SCy Schubert 	}
117341edb306SCy Schubert 	tcp->th_off = (sizeof(*tcp) + canip->ah_optlen) >> 2;
117441edb306SCy Schubert 	inc_anipheaders(canip->ah_optlen);
117541edb306SCy Schubert }
117641edb306SCy Schubert 
117741edb306SCy Schubert 
new_udpheader(void)1178efeb8bffSCy Schubert void new_udpheader(void)
117941edb306SCy Schubert {
118041edb306SCy Schubert 	if ((ip->ip_p) && (ip->ip_p != IPPROTO_UDP)) {
118141edb306SCy Schubert 		fprintf(stderr, "protocol %d specified with UDP!\n", ip->ip_p);
118241edb306SCy Schubert 		return;
118341edb306SCy Schubert 	}
118441edb306SCy Schubert 	ip->ip_p = IPPROTO_UDP;
118541edb306SCy Schubert 
118641edb306SCy Schubert 	udp = (udphdr_t *)new_header(IPPROTO_UDP);
118741edb306SCy Schubert 	udp->uh_ulen = sizeof(*udp);
118841edb306SCy Schubert }
118941edb306SCy Schubert 
119041edb306SCy Schubert 
set_udplen(arg)119141edb306SCy Schubert void set_udplen(arg)
119241edb306SCy Schubert char **arg;
119341edb306SCy Schubert {
119441edb306SCy Schubert 	int len;
119541edb306SCy Schubert 
119641edb306SCy Schubert 	len = strtol(*arg, NULL, 0);
119741edb306SCy Schubert 	inc_anipheaders(len - udp->uh_ulen);
119841edb306SCy Schubert 	udp->uh_ulen = len;
119941edb306SCy Schubert 	free(*arg);
120041edb306SCy Schubert 	*arg = NULL;
120141edb306SCy Schubert }
120241edb306SCy Schubert 
120341edb306SCy Schubert 
set_udpsum(char ** arg)1204efeb8bffSCy Schubert void set_udpsum(char **arg)
120541edb306SCy Schubert {
120641edb306SCy Schubert 	udp->uh_sum = strtol(*arg, NULL, 0);
120741edb306SCy Schubert 	free(*arg);
120841edb306SCy Schubert 	*arg = NULL;
120941edb306SCy Schubert }
121041edb306SCy Schubert 
121141edb306SCy Schubert 
prep_packet(void)1212efeb8bffSCy Schubert void prep_packet(void)
121341edb306SCy Schubert {
121441edb306SCy Schubert 	iface_t *ifp;
121541edb306SCy Schubert 	struct in_addr gwip;
121641edb306SCy Schubert 
121741edb306SCy Schubert 	ifp = sending.snd_if;
121841edb306SCy Schubert 	if (!ifp) {
121941edb306SCy Schubert 		fprintf(stderr, "no interface defined for sending!\n");
122041edb306SCy Schubert 		return;
122141edb306SCy Schubert 	}
122241edb306SCy Schubert 	if (ifp->if_fd == -1)
122341edb306SCy Schubert 		ifp->if_fd = initdevice(ifp->if_name, 5);
122441edb306SCy Schubert 	gwip = sending.snd_gw;
122541edb306SCy Schubert 	if (!gwip.s_addr) {
122641edb306SCy Schubert 		if (aniphead == NULL) {
122741edb306SCy Schubert 			fprintf(stderr,
122841edb306SCy Schubert 				"no destination address defined for sending\n");
122941edb306SCy Schubert 			return;
123041edb306SCy Schubert 		}
123141edb306SCy Schubert 		gwip = aniphead->ah_ip->ip_dst;
123241edb306SCy Schubert 	}
123341edb306SCy Schubert 	(void) send_ip(ifp->if_fd, ifp->if_MTU, (ip_t *)ipbuffer, gwip, 2);
123441edb306SCy Schubert }
123541edb306SCy Schubert 
123641edb306SCy Schubert 
packet_done(void)1237efeb8bffSCy Schubert void packet_done(void)
123841edb306SCy Schubert {
123941edb306SCy Schubert 	char    outline[80];
124041edb306SCy Schubert 	int     i, j, k;
124141edb306SCy Schubert 	u_char  *s = (u_char *)ipbuffer, *t = (u_char *)outline;
124241edb306SCy Schubert 
124341edb306SCy Schubert 	if (opts & OPT_VERBOSE) {
124441edb306SCy Schubert 		ip->ip_len = htons(ip->ip_len);
124541edb306SCy Schubert 		for (i = ntohs(ip->ip_len), j = 0; i; i--, j++, s++) {
124641edb306SCy Schubert 			if (j && !(j & 0xf)) {
124741edb306SCy Schubert 				*t++ = '\n';
124841edb306SCy Schubert 				*t = '\0';
124941edb306SCy Schubert 				fputs(outline, stdout);
125041edb306SCy Schubert 				fflush(stdout);
125141edb306SCy Schubert 				t = (u_char *)outline;
125241edb306SCy Schubert 				*t = '\0';
125341edb306SCy Schubert 			}
125441edb306SCy Schubert 			sprintf((char *)t, "%02x", *s & 0xff);
125541edb306SCy Schubert 			t += 2;
125641edb306SCy Schubert 			if (!((j + 1) & 0xf)) {
125741edb306SCy Schubert 				s -= 15;
125841edb306SCy Schubert 				sprintf((char *)t, "	");
125941edb306SCy Schubert 				t += 8;
126041edb306SCy Schubert 				for (k = 16; k; k--, s++)
126141edb306SCy Schubert 					*t++ = (isprint(*s) ? *s : '.');
126241edb306SCy Schubert 				s--;
126341edb306SCy Schubert 			}
126441edb306SCy Schubert 
126541edb306SCy Schubert 			if ((j + 1) & 0xf)
126641edb306SCy Schubert 				*t++ = ' ';;
126741edb306SCy Schubert 		}
126841edb306SCy Schubert 
126941edb306SCy Schubert 		if (j & 0xf) {
127041edb306SCy Schubert 			for (k = 16 - (j & 0xf); k; k--) {
127141edb306SCy Schubert 				*t++ = ' ';
127241edb306SCy Schubert 				*t++ = ' ';
127341edb306SCy Schubert 				*t++ = ' ';
127441edb306SCy Schubert 			}
127541edb306SCy Schubert 			sprintf((char *)t, "       ");
127641edb306SCy Schubert 			t += 7;
127741edb306SCy Schubert 			s -= j & 0xf;
127841edb306SCy Schubert 			for (k = j & 0xf; k; k--, s++)
127941edb306SCy Schubert 				*t++ = (isprint(*s) ? *s : '.');
128041edb306SCy Schubert 			*t++ = '\n';
128141edb306SCy Schubert 			*t = '\0';
128241edb306SCy Schubert 		}
128341edb306SCy Schubert 		fputs(outline, stdout);
128441edb306SCy Schubert 		fflush(stdout);
128541edb306SCy Schubert 		ip->ip_len = ntohs(ip->ip_len);
128641edb306SCy Schubert 	}
128741edb306SCy Schubert 
128841edb306SCy Schubert 	prep_packet();
128941edb306SCy Schubert 	free_aniplist();
129041edb306SCy Schubert }
129141edb306SCy Schubert 
129241edb306SCy Schubert 
new_interface(void)1293efeb8bffSCy Schubert void new_interface(void)
129441edb306SCy Schubert {
129541edb306SCy Schubert 	cifp = (iface_t *)calloc(1, sizeof(iface_t));
129641edb306SCy Schubert 	*iftail = cifp;
129741edb306SCy Schubert 	iftail = &cifp->if_next;
129841edb306SCy Schubert 	cifp->if_fd = -1;
129941edb306SCy Schubert }
130041edb306SCy Schubert 
130141edb306SCy Schubert 
check_interface(void)1302efeb8bffSCy Schubert void check_interface(void)
130341edb306SCy Schubert {
130441edb306SCy Schubert 	if (!cifp->if_name || !*cifp->if_name)
130541edb306SCy Schubert 		fprintf(stderr, "No interface name given!\n");
130641edb306SCy Schubert 	if (!cifp->if_MTU || !*cifp->if_name)
130741edb306SCy Schubert 		fprintf(stderr, "Interface %s has an MTU of 0!\n",
130841edb306SCy Schubert 			cifp->if_name);
130941edb306SCy Schubert }
131041edb306SCy Schubert 
131141edb306SCy Schubert 
set_ifname(char ** arg)1312efeb8bffSCy Schubert void set_ifname(char **arg)
131341edb306SCy Schubert {
131441edb306SCy Schubert 	cifp->if_name = *arg;
131541edb306SCy Schubert 	*arg = NULL;
131641edb306SCy Schubert }
131741edb306SCy Schubert 
131841edb306SCy Schubert 
set_ifmtu(int arg)1319efeb8bffSCy Schubert void set_ifmtu(int arg)
132041edb306SCy Schubert {
132141edb306SCy Schubert 	cifp->if_MTU = arg;
132241edb306SCy Schubert }
132341edb306SCy Schubert 
132441edb306SCy Schubert 
set_ifv4addr(char ** arg)1325efeb8bffSCy Schubert void set_ifv4addr(char **arg)
132641edb306SCy Schubert {
132741edb306SCy Schubert 	cifp->if_addr = getipv4addr(*arg);
132841edb306SCy Schubert 	free(*arg);
132941edb306SCy Schubert 	*arg = NULL;
133041edb306SCy Schubert }
133141edb306SCy Schubert 
133241edb306SCy Schubert 
set_ifeaddr(char ** arg)1333efeb8bffSCy Schubert void set_ifeaddr(char **arg)
133441edb306SCy Schubert {
133541edb306SCy Schubert 	(void) geteaddr(*arg, &cifp->if_eaddr);
133641edb306SCy Schubert 	free(*arg);
133741edb306SCy Schubert 	*arg = NULL;
133841edb306SCy Schubert }
133941edb306SCy Schubert 
134041edb306SCy Schubert 
new_arp(void)1341efeb8bffSCy Schubert void new_arp(void)
134241edb306SCy Schubert {
134341edb306SCy Schubert 	carp = (arp_t *)calloc(1, sizeof(arp_t));
134441edb306SCy Schubert 	*arptail = carp;
134541edb306SCy Schubert 	arptail = &carp->arp_next;
134641edb306SCy Schubert }
134741edb306SCy Schubert 
134841edb306SCy Schubert 
set_arpeaddr(char ** arg)1349efeb8bffSCy Schubert void set_arpeaddr(char **arg)
135041edb306SCy Schubert {
135141edb306SCy Schubert 	(void) geteaddr(*arg, &carp->arp_eaddr);
135241edb306SCy Schubert 	free(*arg);
135341edb306SCy Schubert 	*arg = NULL;
135441edb306SCy Schubert }
135541edb306SCy Schubert 
135641edb306SCy Schubert 
set_arpv4addr(char ** arg)1357efeb8bffSCy Schubert void set_arpv4addr(char **arg)
135841edb306SCy Schubert {
135941edb306SCy Schubert 	carp->arp_addr = getipv4addr(*arg);
136041edb306SCy Schubert 	free(*arg);
136141edb306SCy Schubert 	*arg = NULL;
136241edb306SCy Schubert }
136341edb306SCy Schubert 
136441edb306SCy Schubert 
arp_getipv4(char * ip,char * addr)1365efeb8bffSCy Schubert int arp_getipv4(char *ip, char *addr)
136641edb306SCy Schubert {
136741edb306SCy Schubert 	arp_t *a;
136841edb306SCy Schubert 
136941edb306SCy Schubert 	for (a = arplist; a; a = a->arp_next)
137041edb306SCy Schubert 		if (!bcmp(ip, (char *)&a->arp_addr, 4)) {
137141edb306SCy Schubert 			bcopy((char *)&a->arp_eaddr, addr, 6);
13722582ae57SCy Schubert 			return(0);
137341edb306SCy Schubert 		}
13742582ae57SCy Schubert 	return(-1);
137541edb306SCy Schubert }
137641edb306SCy Schubert 
137741edb306SCy Schubert 
reset_send(void)1378efeb8bffSCy Schubert void reset_send(void)
137941edb306SCy Schubert {
138041edb306SCy Schubert 	sending.snd_if = iflist;
138141edb306SCy Schubert 	sending.snd_gw = defrouter;
138241edb306SCy Schubert }
138341edb306SCy Schubert 
138441edb306SCy Schubert 
set_sendif(char ** arg)1385efeb8bffSCy Schubert void set_sendif(char **arg)
138641edb306SCy Schubert {
138741edb306SCy Schubert 	iface_t	*ifp;
138841edb306SCy Schubert 
138941edb306SCy Schubert 	for (ifp = iflist; ifp; ifp = ifp->if_next)
139041edb306SCy Schubert 		if (ifp->if_name && !strcmp(ifp->if_name, *arg))
139141edb306SCy Schubert 			break;
139241edb306SCy Schubert 	sending.snd_if = ifp;
139341edb306SCy Schubert 	if (!ifp)
139441edb306SCy Schubert 		fprintf(stderr, "couldn't find interface %s\n", *arg);
139541edb306SCy Schubert 	free(*arg);
139641edb306SCy Schubert 	*arg = NULL;
139741edb306SCy Schubert }
139841edb306SCy Schubert 
139941edb306SCy Schubert 
set_sendvia(char ** arg)1400efeb8bffSCy Schubert void set_sendvia(char **arg)
140141edb306SCy Schubert {
140241edb306SCy Schubert 	sending.snd_gw = getipv4addr(*arg);
140341edb306SCy Schubert 	free(*arg);
140441edb306SCy Schubert 	*arg = NULL;
140541edb306SCy Schubert }
140641edb306SCy Schubert 
140741edb306SCy Schubert 
set_defaultrouter(char ** arg)1408efeb8bffSCy Schubert void set_defaultrouter(char **arg)
140941edb306SCy Schubert {
141041edb306SCy Schubert 	defrouter = getipv4addr(*arg);
141141edb306SCy Schubert 	free(*arg);
141241edb306SCy Schubert 	*arg = NULL;
141341edb306SCy Schubert }
141441edb306SCy Schubert 
141541edb306SCy Schubert 
new_icmpheader(void)1416efeb8bffSCy Schubert void new_icmpheader(void)
141741edb306SCy Schubert {
141841edb306SCy Schubert 	if ((ip->ip_p) && (ip->ip_p != IPPROTO_ICMP)) {
141941edb306SCy Schubert 		fprintf(stderr, "protocol %d specified with ICMP!\n",
142041edb306SCy Schubert 			ip->ip_p);
142141edb306SCy Schubert 		return;
142241edb306SCy Schubert 	}
142341edb306SCy Schubert 	ip->ip_p = IPPROTO_ICMP;
142441edb306SCy Schubert 	icmp = (icmphdr_t *)new_header(IPPROTO_ICMP);
142541edb306SCy Schubert }
142641edb306SCy Schubert 
142741edb306SCy Schubert 
set_icmpcode(int code)1428efeb8bffSCy Schubert void set_icmpcode(int code)
142941edb306SCy Schubert {
143041edb306SCy Schubert 	icmp->icmp_code = code;
143141edb306SCy Schubert }
143241edb306SCy Schubert 
143341edb306SCy Schubert 
set_icmptype(int type)1434efeb8bffSCy Schubert void set_icmptype(int type)
143541edb306SCy Schubert {
143641edb306SCy Schubert 	icmp->icmp_type = type;
143741edb306SCy Schubert }
143841edb306SCy Schubert 
143941edb306SCy Schubert 
set_icmpcodetok(char ** code)1440efeb8bffSCy Schubert void set_icmpcodetok(char **code)
144141edb306SCy Schubert {
144241edb306SCy Schubert 	char	*s;
144341edb306SCy Schubert 	int	i;
144441edb306SCy Schubert 
144541edb306SCy Schubert 	for (i = 0; (s = icmpcodes[i]); i++)
144641edb306SCy Schubert 		if (!strcmp(s, *code)) {
144741edb306SCy Schubert 			icmp->icmp_code = i;
144841edb306SCy Schubert 			break;
144941edb306SCy Schubert 		}
145041edb306SCy Schubert 	if (!s)
145141edb306SCy Schubert 		fprintf(stderr, "unknown ICMP code %s\n", *code);
145241edb306SCy Schubert 	free(*code);
145341edb306SCy Schubert 	*code = NULL;
145441edb306SCy Schubert }
145541edb306SCy Schubert 
145641edb306SCy Schubert 
set_icmptypetok(char ** type)1457efeb8bffSCy Schubert void set_icmptypetok(char **type)
145841edb306SCy Schubert {
145941edb306SCy Schubert 	char	*s;
146041edb306SCy Schubert 	int	i, done = 0;
146141edb306SCy Schubert 
146241edb306SCy Schubert 	for (i = 0; !(s = icmptypes[i]) || strcmp(s, "END"); i++)
146341edb306SCy Schubert 		if (s && !strcmp(s, *type)) {
146441edb306SCy Schubert 			icmp->icmp_type = i;
146541edb306SCy Schubert 			done = 1;
146641edb306SCy Schubert 			break;
146741edb306SCy Schubert 		}
146841edb306SCy Schubert 	if (!done)
146941edb306SCy Schubert 		fprintf(stderr, "unknown ICMP type %s\n", *type);
147041edb306SCy Schubert 	free(*type);
147141edb306SCy Schubert 	*type = NULL;
147241edb306SCy Schubert }
147341edb306SCy Schubert 
147441edb306SCy Schubert 
set_icmpid(int arg)1475efeb8bffSCy Schubert void set_icmpid(int arg)
147641edb306SCy Schubert {
147741edb306SCy Schubert 	icmp->icmp_id = htons(arg);
147841edb306SCy Schubert }
147941edb306SCy Schubert 
148041edb306SCy Schubert 
set_icmpseq(int arg)1481efeb8bffSCy Schubert void set_icmpseq(int arg)
148241edb306SCy Schubert {
148341edb306SCy Schubert 	icmp->icmp_seq = htons(arg);
148441edb306SCy Schubert }
148541edb306SCy Schubert 
148641edb306SCy Schubert 
set_icmpotime(int arg)1487efeb8bffSCy Schubert void set_icmpotime(int arg)
148841edb306SCy Schubert {
148941edb306SCy Schubert 	icmp->icmp_otime = htonl(arg);
149041edb306SCy Schubert }
149141edb306SCy Schubert 
149241edb306SCy Schubert 
set_icmprtime(int arg)1493efeb8bffSCy Schubert void set_icmprtime(int arg)
149441edb306SCy Schubert {
149541edb306SCy Schubert 	icmp->icmp_rtime = htonl(arg);
149641edb306SCy Schubert }
149741edb306SCy Schubert 
149841edb306SCy Schubert 
set_icmpttime(int arg)1499efeb8bffSCy Schubert void set_icmpttime(int arg)
150041edb306SCy Schubert {
150141edb306SCy Schubert 	icmp->icmp_ttime = htonl(arg);
150241edb306SCy Schubert }
150341edb306SCy Schubert 
150441edb306SCy Schubert 
set_icmpmtu(int arg)1505efeb8bffSCy Schubert void set_icmpmtu(int arg)
150641edb306SCy Schubert {
150741edb306SCy Schubert 	icmp->icmp_nextmtu = htons(arg);
150841edb306SCy Schubert }
150941edb306SCy Schubert 
151041edb306SCy Schubert 
set_redir(int redir,char ** arg)1511efeb8bffSCy Schubert void set_redir(int redir, char **arg)
151241edb306SCy Schubert {
151341edb306SCy Schubert 	icmp->icmp_code = redir;
151441edb306SCy Schubert 	icmp->icmp_gwaddr = getipv4addr(*arg);
151541edb306SCy Schubert 	free(*arg);
151641edb306SCy Schubert 	*arg = NULL;
151741edb306SCy Schubert }
151841edb306SCy Schubert 
151941edb306SCy Schubert 
set_icmppprob(int num)1520efeb8bffSCy Schubert void set_icmppprob(int num)
152141edb306SCy Schubert {
152241edb306SCy Schubert 	icmp->icmp_pptr = num;
152341edb306SCy Schubert }
152441edb306SCy Schubert 
152541edb306SCy Schubert 
new_ipv4opt(void)1526efeb8bffSCy Schubert void new_ipv4opt(void)
152741edb306SCy Schubert {
152841edb306SCy Schubert 	new_header(-2);
152941edb306SCy Schubert }
153041edb306SCy Schubert 
153141edb306SCy Schubert 
add_ipopt(int state,void * ptr)1532efeb8bffSCy Schubert void add_ipopt(int state, void *ptr)
153341edb306SCy Schubert {
153441edb306SCy Schubert 	struct ipopt_names *io;
153541edb306SCy Schubert 	struct statetoopt *sto;
153641edb306SCy Schubert 	char numbuf[16], *arg, **param = ptr;
153741edb306SCy Schubert 	int inc, hlen;
153841edb306SCy Schubert 
153941edb306SCy Schubert 	if (state == IL_IPO_RR || state == IL_IPO_SATID) {
154041edb306SCy Schubert 		if (param)
154141edb306SCy Schubert 			snprintf(numbuf, sizeof(numbuf), "%d", *(int *)param);
154241edb306SCy Schubert 		else
154341edb306SCy Schubert 			strcpy(numbuf, "0");
154441edb306SCy Schubert 		arg = numbuf;
154541edb306SCy Schubert 	} else
154641edb306SCy Schubert 		arg = param ? *param : NULL;
154741edb306SCy Schubert 
154841edb306SCy Schubert 	if (canip->ah_next) {
154941edb306SCy Schubert 		fprintf(stderr, "cannot specify options after data body\n");
155041edb306SCy Schubert 		return;
155141edb306SCy Schubert 	}
155241edb306SCy Schubert 	for (sto = toipopts; sto->sto_st; sto++)
155341edb306SCy Schubert 		if (sto->sto_st == state)
155441edb306SCy Schubert 			break;
155541edb306SCy Schubert 	if (!sto->sto_st) {
155641edb306SCy Schubert 		fprintf(stderr, "No mapping for state %d to IP option\n",
155741edb306SCy Schubert 			state);
155841edb306SCy Schubert 		return;
155941edb306SCy Schubert 	}
156041edb306SCy Schubert 
156141edb306SCy Schubert 	hlen = sizeof(ip_t) + canip->ah_optlen;
156241edb306SCy Schubert 	for (io = ionames; io->on_name; io++)
156341edb306SCy Schubert 		if (io->on_value == sto->sto_op)
156441edb306SCy Schubert 			break;
156541edb306SCy Schubert 	canip->ah_lastopt = io->on_value;
156641edb306SCy Schubert 
156741edb306SCy Schubert 	if (io->on_name) {
156841edb306SCy Schubert 		inc = addipopt((char *)ip + hlen, io, hlen - sizeof(ip_t),arg);
156941edb306SCy Schubert 		if (inc > 0) {
157041edb306SCy Schubert 			while (inc & 3) {
157141edb306SCy Schubert 				((char *)ip)[sizeof(*ip) + inc] = IPOPT_NOP;
157241edb306SCy Schubert 				canip->ah_lastopt = IPOPT_NOP;
157341edb306SCy Schubert 				inc++;
157441edb306SCy Schubert 			}
157541edb306SCy Schubert 			hlen += inc;
157641edb306SCy Schubert 		}
157741edb306SCy Schubert 	}
157841edb306SCy Schubert 
157941edb306SCy Schubert 	canip->ah_optlen = hlen - sizeof(ip_t);
158041edb306SCy Schubert 
158141edb306SCy Schubert 	if (state != IL_IPO_RR && state != IL_IPO_SATID)
158241edb306SCy Schubert 		if (param && *param) {
158341edb306SCy Schubert 			free(*param);
158441edb306SCy Schubert 			*param = NULL;
158541edb306SCy Schubert 		}
158641edb306SCy Schubert 	sclass = NULL;
158741edb306SCy Schubert }
158841edb306SCy Schubert 
158941edb306SCy Schubert 
end_ipopt(void)1590efeb8bffSCy Schubert void end_ipopt(void)
159141edb306SCy Schubert {
159241edb306SCy Schubert 	int pad;
159341edb306SCy Schubert 	char *s, *buf = (char *)ip;
159441edb306SCy Schubert 
159541edb306SCy Schubert 	/*
159641edb306SCy Schubert 	 * pad out so that we have a multiple of 4 bytes in size fo the
159741edb306SCy Schubert 	 * options.  make sure last byte is EOL.
159841edb306SCy Schubert 	 */
159941edb306SCy Schubert 	if (canip->ah_lastopt == IPOPT_NOP) {
160041edb306SCy Schubert 		buf[sizeof(*ip) + canip->ah_optlen - 1] = IPOPT_EOL;
160141edb306SCy Schubert 	} else if (canip->ah_lastopt != IPOPT_EOL) {
160241edb306SCy Schubert 		s = buf + sizeof(*ip) + canip->ah_optlen;
160341edb306SCy Schubert 
160441edb306SCy Schubert 		for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) {
160541edb306SCy Schubert 			*s++ = IPOPT_NOP;
160641edb306SCy Schubert 			*s = IPOPT_EOL;
160741edb306SCy Schubert 			canip->ah_optlen++;
160841edb306SCy Schubert 		}
160941edb306SCy Schubert 		canip->ah_optlen++;
161041edb306SCy Schubert 	} else {
161141edb306SCy Schubert 		s = buf + sizeof(*ip) + canip->ah_optlen - 1;
161241edb306SCy Schubert 
161341edb306SCy Schubert 		for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) {
161441edb306SCy Schubert 			*s++ = IPOPT_NOP;
161541edb306SCy Schubert 			*s = IPOPT_EOL;
161641edb306SCy Schubert 			canip->ah_optlen++;
161741edb306SCy Schubert 		}
161841edb306SCy Schubert 	}
161941edb306SCy Schubert 	ip->ip_hl = (sizeof(*ip) + canip->ah_optlen) >> 2;
162041edb306SCy Schubert 	inc_anipheaders(canip->ah_optlen);
162141edb306SCy Schubert 	free_anipheader();
162241edb306SCy Schubert }
162341edb306SCy Schubert 
162441edb306SCy Schubert 
set_secclass(char ** arg)1625efeb8bffSCy Schubert void set_secclass(char **arg)
162641edb306SCy Schubert {
162741edb306SCy Schubert 	sclass = *arg;
162841edb306SCy Schubert 	*arg = NULL;
162941edb306SCy Schubert }
163041edb306SCy Schubert 
163141edb306SCy Schubert 
free_anipheader(void)1632efeb8bffSCy Schubert void free_anipheader(void)
163341edb306SCy Schubert {
163441edb306SCy Schubert 	aniphdr_t *aip;
163541edb306SCy Schubert 
163641edb306SCy Schubert 	aip = canip;
163741edb306SCy Schubert 	if ((canip = aip->ah_prev)) {
163841edb306SCy Schubert 		canip->ah_next = NULL;
163941edb306SCy Schubert 		aniptail = &canip->ah_next;
164041edb306SCy Schubert 	}
164141edb306SCy Schubert 
164241edb306SCy Schubert 	if (canip)
164341edb306SCy Schubert 		free(aip);
164441edb306SCy Schubert }
164541edb306SCy Schubert 
164641edb306SCy Schubert 
end_ipv4(void)1647efeb8bffSCy Schubert void end_ipv4(void)
164841edb306SCy Schubert {
164941edb306SCy Schubert 	aniphdr_t *aip;
165041edb306SCy Schubert 
165141edb306SCy Schubert 	ip->ip_sum = 0;
165241edb306SCy Schubert 	ip->ip_len = htons(ip->ip_len);
165341edb306SCy Schubert 	ip->ip_sum = chksum((u_short *)ip, ip->ip_hl << 2);
165441edb306SCy Schubert 	ip->ip_len = ntohs(ip->ip_len);
165541edb306SCy Schubert 	free_anipheader();
165641edb306SCy Schubert 	for (aip = aniphead, ip = NULL; aip; aip = aip->ah_next)
165741edb306SCy Schubert 		if (aip->ah_p == IPPROTO_IP)
165841edb306SCy Schubert 			ip = aip->ah_ip;
165941edb306SCy Schubert }
166041edb306SCy Schubert 
166141edb306SCy Schubert 
end_icmp(void)1662efeb8bffSCy Schubert void end_icmp(void)
166341edb306SCy Schubert {
166441edb306SCy Schubert 	aniphdr_t *aip;
166541edb306SCy Schubert 
166641edb306SCy Schubert 	icmp->icmp_cksum = 0;
166741edb306SCy Schubert 	icmp->icmp_cksum = chksum((u_short *)icmp, canip->ah_len);
166841edb306SCy Schubert 	free_anipheader();
166941edb306SCy Schubert 	for (aip = aniphead, icmp = NULL; aip; aip = aip->ah_next)
167041edb306SCy Schubert 		if (aip->ah_p == IPPROTO_ICMP)
167141edb306SCy Schubert 			icmp = aip->ah_icmp;
167241edb306SCy Schubert }
167341edb306SCy Schubert 
167441edb306SCy Schubert 
end_udp(void)1675efeb8bffSCy Schubert void end_udp(void)
167641edb306SCy Schubert {
167741edb306SCy Schubert 	u_long	sum;
167841edb306SCy Schubert 	aniphdr_t *aip;
167941edb306SCy Schubert 	ip_t	iptmp;
168041edb306SCy Schubert 
168141edb306SCy Schubert 	bzero((char *)&iptmp, sizeof(iptmp));
168241edb306SCy Schubert 	iptmp.ip_p = ip->ip_p;
168341edb306SCy Schubert 	iptmp.ip_src = ip->ip_src;
168441edb306SCy Schubert 	iptmp.ip_dst = ip->ip_dst;
168541edb306SCy Schubert 	iptmp.ip_len = htons(ip->ip_len - (ip->ip_hl << 2));
168641edb306SCy Schubert 	sum = p_chksum((u_short *)&iptmp, (u_int)sizeof(iptmp));
168741edb306SCy Schubert 	udp->uh_ulen = htons(udp->uh_ulen);
168841edb306SCy Schubert 	udp->uh_sum = c_chksum((u_short *)udp, (u_int)ntohs(iptmp.ip_len), sum);
168941edb306SCy Schubert 	free_anipheader();
169041edb306SCy Schubert 	for (aip = aniphead, udp = NULL; aip; aip = aip->ah_next)
169141edb306SCy Schubert 		if (aip->ah_p == IPPROTO_UDP)
169241edb306SCy Schubert 			udp = aip->ah_udp;
169341edb306SCy Schubert }
169441edb306SCy Schubert 
169541edb306SCy Schubert 
end_tcp(void)1696efeb8bffSCy Schubert void end_tcp(void)
169741edb306SCy Schubert {
169841edb306SCy Schubert 	u_long	sum;
169941edb306SCy Schubert 	aniphdr_t *aip;
170041edb306SCy Schubert 	ip_t	iptmp;
170141edb306SCy Schubert 
170241edb306SCy Schubert 	bzero((char *)&iptmp, sizeof(iptmp));
170341edb306SCy Schubert 	iptmp.ip_p = ip->ip_p;
170441edb306SCy Schubert 	iptmp.ip_src = ip->ip_src;
170541edb306SCy Schubert 	iptmp.ip_dst = ip->ip_dst;
170641edb306SCy Schubert 	iptmp.ip_len = htons(ip->ip_len - (ip->ip_hl << 2));
170741edb306SCy Schubert 	sum = p_chksum((u_short *)&iptmp, (u_int)sizeof(iptmp));
170841edb306SCy Schubert 	tcp->th_sum = 0;
170941edb306SCy Schubert 	tcp->th_sum = c_chksum((u_short *)tcp, (u_int)ntohs(iptmp.ip_len), sum);
171041edb306SCy Schubert 	free_anipheader();
171141edb306SCy Schubert 	for (aip = aniphead, tcp = NULL; aip; aip = aip->ah_next)
171241edb306SCy Schubert 		if (aip->ah_p == IPPROTO_TCP)
171341edb306SCy Schubert 			tcp = aip->ah_tcp;
171441edb306SCy Schubert }
171541edb306SCy Schubert 
171641edb306SCy Schubert 
end_data(void)1717efeb8bffSCy Schubert void end_data(void)
171841edb306SCy Schubert {
171941edb306SCy Schubert 	free_anipheader();
172041edb306SCy Schubert }
172141edb306SCy Schubert 
172241edb306SCy Schubert 
iplang(FILE * fp)1723efeb8bffSCy Schubert void iplang(FILE *fp)
172441edb306SCy Schubert {
172541edb306SCy Schubert 	yyin = fp;
172641edb306SCy Schubert 
172741edb306SCy Schubert 	yydebug = (opts & OPT_DEBUG) ? 1 : 0;
172841edb306SCy Schubert 
172941edb306SCy Schubert 	while (!feof(fp))
173041edb306SCy Schubert 		yyparse();
173141edb306SCy Schubert }
173241edb306SCy Schubert 
173341edb306SCy Schubert 
c_chksum(u_short * buf,u_int len,u_long init)1734efeb8bffSCy Schubert u_short	c_chksum(u_short *buf, u_int len, u_long init)
173541edb306SCy Schubert {
173641edb306SCy Schubert 	u_long	sum = init;
173741edb306SCy Schubert 	int	nwords = len >> 1;
173841edb306SCy Schubert 
173941edb306SCy Schubert 	for(; nwords > 0; nwords--)
174041edb306SCy Schubert 		sum += *buf++;
174141edb306SCy Schubert 	sum = (sum>>16) + (sum & 0xffff);
174241edb306SCy Schubert 	sum += (sum >>16);
174341edb306SCy Schubert 	return(~sum);
174441edb306SCy Schubert }
174541edb306SCy Schubert 
174641edb306SCy Schubert 
p_chksum(u_short * buf,u_int len)1747efeb8bffSCy Schubert u_long	p_chksum(u_short *buf, u_int len)
174841edb306SCy Schubert {
174941edb306SCy Schubert 	u_long	sum = 0;
175041edb306SCy Schubert 	int	nwords = len >> 1;
175141edb306SCy Schubert 
175241edb306SCy Schubert 	for(; nwords > 0; nwords--)
175341edb306SCy Schubert 		sum += *buf++;
17542582ae57SCy Schubert 	return(sum);
175541edb306SCy Schubert }
1756