1145519Sdarrenr/*	$FreeBSD$	*/
2145519Sdarrenr
331183Speter%{
431183Speter/*
5255332Scy * Copyright (C) 2012 by Darren Reed.
631183Speter *
7145519Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
831183Speter *
9161357Sguido * Id: iplang_y.y,v 2.9.2.4 2006/03/17 12:11:29 darrenr Exp $
1063537Sarchie * $FreeBSD$
1131183Speter */
1253024Sguido
1331183Speter#include <stdio.h>
1431183Speter#include <string.h>
1531183Speter#include <fcntl.h>
1631183Speter#if !defined(__SVR4) && !defined(__svr4__)
17170268Sdarrenr# include <strings.h>
1831183Speter#else
19170268Sdarrenr# include <sys/byteorder.h>
2031183Speter#endif
2131183Speter#include <sys/types.h>
2231183Speter#include <sys/stat.h>
2331183Speter#include <sys/param.h>
2431183Speter#include <sys/time.h>
2531183Speter#include <stdlib.h>
2631183Speter#include <unistd.h>
2731183Speter#include <stddef.h>
2831183Speter#include <sys/socket.h>
29255332Scy#include <net/if.h>
3031183Speter#include <netinet/in.h>
3131183Speter#include <netinet/in_systm.h>
3231183Speter#include <netinet/ip.h>
3331183Speter#ifndef	linux
34170268Sdarrenr# include <netinet/ip_var.h>
35255332Scy# include <net/route.h>
36170268Sdarrenr# include <netinet/if_ether.h>
3731183Speter#endif
3831183Speter#include <netdb.h>
3931183Speter#include <arpa/nameser.h>
4031183Speter#include <arpa/inet.h>
4131183Speter#include <resolv.h>
4231183Speter#include <ctype.h>
4331183Speter#include "ipsend.h"
4431183Speter#include "ip_compat.h"
4531183Speter#include "ipf.h"
4631183Speter#include "iplang.h"
4731183Speter
4864591Sdarrenr#if !defined(__NetBSD__) && (!defined(__FreeBSD_version) && \
49145519Sdarrenr    __FreeBSD_version < 400020) && (!SOLARIS || SOLARIS2 < 10)
5031183Speterextern	struct ether_addr *ether_aton __P((char *));
5137074Speter#endif
5231183Speter
5331183Speterextern	int	opts;
5431183Speterextern	struct ipopt_names ionames[];
5531183Speterextern	int	state, state, lineNum, token;
5631183Speterextern	int	yylineno;
5731183Speterextern	char	yytext[];
5831183Speterextern	FILE	*yyin;
5931183Speterint	yylex	__P((void));
6031183Speter#define	YYDEBUG 1
6131183Speter#if !defined(ultrix) && !defined(hpux)
6231183Speterint	yydebug = 1;
6331183Speter#else
6431183Speterextern	int	yydebug;
6531183Speter#endif
6631183Speter
6731183Speteriface_t *iflist = NULL, **iftail = &iflist;
6831183Speteriface_t *cifp = NULL;
6931183Speterarp_t *arplist = NULL, **arptail = &arplist, *carp = NULL;
7031183Speterstruct in_addr defrouter;
7131183Spetersend_t	sending;
7231183Speterchar	*sclass = NULL;
7331183Speteru_short	c_chksum __P((u_short *, u_int, u_long));
7431183Speteru_long	p_chksum __P((u_short *, u_int));
7531183Speter
7631183Speteru_long	ipbuffer[67584/sizeof(u_long)];		/* 66K */
7731183Speteraniphdr_t	*aniphead = NULL, *canip = NULL, **aniptail = &aniphead;
7831183Speterip_t		*ip = NULL;
7931183Speterudphdr_t	*udp = NULL;
8031183Spetertcphdr_t	*tcp = NULL;
8131183Spetericmphdr_t	*icmp = NULL;
8231183Speter
8331183Speterstruct statetoopt {
8431183Speter	int	sto_st;
8531183Speter	int	sto_op;
8631183Speter};
8731183Speter
8831183Speterstruct	in_addr getipv4addr __P((char *arg));
8931183Speteru_short	getportnum __P((char *, char *));
9031183Speterstruct	ether_addr *geteaddr __P((char *, struct ether_addr *));
9131183Spetervoid	*new_header __P((int));
9231183Spetervoid	free_aniplist __P((void));
9331183Spetervoid	inc_anipheaders __P((int));
9431183Spetervoid	new_data __P((void));
9531183Spetervoid	set_datalen __P((char **));
9631183Spetervoid	set_datafile __P((char **));
9731183Spetervoid	set_data __P((char **));
9831183Spetervoid	new_packet __P((void));
9931183Spetervoid	set_ipv4proto __P((char **));
10031183Spetervoid	set_ipv4src __P((char **));
10131183Spetervoid	set_ipv4dst __P((char **));
10231183Spetervoid	set_ipv4off __P((char **));
10331183Spetervoid	set_ipv4v __P((char **));
10431183Spetervoid	set_ipv4hl __P((char **));
10531183Spetervoid	set_ipv4ttl __P((char **));
10631183Spetervoid	set_ipv4tos __P((char **));
10731183Spetervoid	set_ipv4id __P((char **));
10831183Spetervoid	set_ipv4sum __P((char **));
10931183Spetervoid	set_ipv4len __P((char **));
11031183Spetervoid	new_tcpheader __P((void));
11131183Spetervoid	set_tcpsport __P((char **));
11231183Spetervoid	set_tcpdport __P((char **));
11331183Spetervoid	set_tcpseq __P((char **));
11431183Spetervoid	set_tcpack __P((char **));
11531183Spetervoid	set_tcpoff __P((char **));
11631183Spetervoid	set_tcpurp __P((char **));
11731183Spetervoid	set_tcpwin __P((char **));
11831183Spetervoid	set_tcpsum __P((char **));
11931183Spetervoid	set_tcpflags __P((char **));
12031183Spetervoid	set_tcpopt __P((int, char **));
12131183Spetervoid	end_tcpopt __P((void));
12231183Spetervoid	new_udpheader __P((void));
12331183Spetervoid	set_udplen __P((char **));
12431183Spetervoid	set_udpsum __P((char **));
12531183Spetervoid	prep_packet __P((void));
12631183Spetervoid	packet_done __P((void));
12731183Spetervoid	new_interface __P((void));
12831183Spetervoid	check_interface __P((void));
12931183Spetervoid	set_ifname __P((char **));
13031183Spetervoid	set_ifmtu __P((int));
13131183Spetervoid	set_ifv4addr __P((char **));
13231183Spetervoid	set_ifeaddr __P((char **));
13331183Spetervoid	new_arp __P((void));
13431183Spetervoid	set_arpeaddr __P((char **));
13531183Spetervoid	set_arpv4addr __P((char **));
13631183Spetervoid	reset_send __P((void));
13731183Spetervoid	set_sendif __P((char **));
13831183Spetervoid	set_sendvia __P((char **));
13931183Spetervoid	set_defaultrouter __P((char **));
14031183Spetervoid	new_icmpheader __P((void));
14131183Spetervoid	set_icmpcode __P((int));
14231183Spetervoid	set_icmptype __P((int));
14331183Spetervoid	set_icmpcodetok __P((char **));
14431183Spetervoid	set_icmptypetok __P((char **));
14531183Spetervoid	set_icmpid __P((int));
14631183Spetervoid	set_icmpseq __P((int));
14731183Spetervoid	set_icmpotime __P((int));
14831183Spetervoid	set_icmprtime __P((int));
14931183Spetervoid	set_icmpttime __P((int));
15031183Spetervoid	set_icmpmtu __P((int));
15131183Spetervoid	set_redir __P((int, char **));
15231183Spetervoid	new_ipv4opt __P((void));
15331183Spetervoid	set_icmppprob __P((int));
15431183Spetervoid	add_ipopt __P((int, void *));
15531183Spetervoid	end_ipopt __P((void));
15631183Spetervoid	set_secclass __P((char **));
15731183Spetervoid	free_anipheader __P((void));
15831183Spetervoid	end_ipv4 __P((void));
15931183Spetervoid	end_icmp __P((void));
16031183Spetervoid	end_udp __P((void));
16131183Spetervoid	end_tcp __P((void));
16231183Spetervoid	end_data __P((void));
16331183Spetervoid	yyerror __P((char *));
16431183Spetervoid	iplang __P((FILE *));
16555924Sguidoint	arp_getipv4 __P((char *, char *));
16631183Speterint	yyparse __P((void));
16731183Speter%}
16831183Speter%union {
16931183Speter	char	*str;
17031183Speter	int	num;
17131183Speter}
17231183Speter%token	<num> IL_NUMBER
17331183Speter%type	<num> number digits optnumber
17431183Speter%token	<str> IL_TOKEN
17531183Speter%type	<str> token optoken
17631183Speter%token	IL_HEXDIGIT IL_COLON IL_DOT IL_EOF IL_COMMENT
17731183Speter%token	IL_INTERFACE IL_IFNAME IL_MTU IL_EADDR
17831183Speter%token	IL_IPV4 IL_V4PROTO IL_V4SRC IL_V4DST IL_V4OFF IL_V4V IL_V4HL IL_V4TTL
17931183Speter%token	IL_V4TOS IL_V4SUM IL_V4LEN IL_V4OPT IL_V4ID
18031183Speter%token	IL_TCP IL_SPORT IL_DPORT IL_TCPFL IL_TCPSEQ IL_TCPACK IL_TCPOFF
18131183Speter%token	IL_TCPWIN IL_TCPSUM IL_TCPURP IL_TCPOPT IL_TCPO_NOP IL_TCPO_EOL
18231183Speter%token	IL_TCPO_MSS IL_TCPO_WSCALE IL_TCPO_TS
18331183Speter%token	IL_UDP IL_UDPLEN IL_UDPSUM
18431183Speter%token	IL_ICMP IL_ICMPTYPE IL_ICMPCODE
18531183Speter%token	IL_SEND IL_VIA
18631183Speter%token	IL_ARP
18731183Speter%token	IL_DEFROUTER
18831183Speter%token	IL_SUM IL_OFF IL_LEN IL_V4ADDR IL_OPT
18931183Speter%token	IL_DATA IL_DLEN IL_DVALUE IL_DFILE
19031183Speter%token	IL_IPO_NOP IL_IPO_RR IL_IPO_ZSU IL_IPO_MTUP IL_IPO_MTUR IL_IPO_EOL
19131183Speter%token	IL_IPO_TS IL_IPO_TR IL_IPO_SEC IL_IPO_LSRR IL_IPO_ESEC
19231183Speter%token	IL_IPO_SATID IL_IPO_SSRR IL_IPO_ADDEXT IL_IPO_VISA IL_IPO_IMITD
19331183Speter%token	IL_IPO_EIP IL_IPO_FINN IL_IPO_SECCLASS IL_IPO_CIPSO IL_IPO_ENCODE
19434739Speter%token	<str> IL_IPS_RESERV4 IL_IPS_TOPSECRET IL_IPS_SECRET IL_IPS_RESERV3
19534739Speter%token	<str> IL_IPS_CONFID IL_IPS_UNCLASS IL_IPS_RESERV2 IL_IPS_RESERV1
19631183Speter%token	IL_ICMP_ECHOREPLY IL_ICMP_UNREACH IL_ICMP_UNREACH_NET
19731183Speter%token	IL_ICMP_UNREACH_HOST IL_ICMP_UNREACH_PROTOCOL IL_ICMP_UNREACH_PORT
19831183Speter%token	IL_ICMP_UNREACH_NEEDFRAG IL_ICMP_UNREACH_SRCFAIL
19931183Speter%token	IL_ICMP_UNREACH_NET_UNKNOWN IL_ICMP_UNREACH_HOST_UNKNOWN
20031183Speter%token	IL_ICMP_UNREACH_ISOLATED IL_ICMP_UNREACH_NET_PROHIB
20131183Speter%token	IL_ICMP_UNREACH_HOST_PROHIB IL_ICMP_UNREACH_TOSNET
20231183Speter%token	IL_ICMP_UNREACH_TOSHOST IL_ICMP_UNREACH_FILTER_PROHIB
20331183Speter%token	IL_ICMP_UNREACH_HOST_PRECEDENCE IL_ICMP_UNREACH_PRECEDENCE_CUTOFF
20431183Speter%token	IL_ICMP_SOURCEQUENCH IL_ICMP_REDIRECT IL_ICMP_REDIRECT_NET
20531183Speter%token	IL_ICMP_REDIRECT_HOST IL_ICMP_REDIRECT_TOSNET
20631183Speter%token	IL_ICMP_REDIRECT_TOSHOST IL_ICMP_ECHO IL_ICMP_ROUTERADVERT
20731183Speter%token	IL_ICMP_ROUTERSOLICIT IL_ICMP_TIMXCEED IL_ICMP_TIMXCEED_INTRANS
20831183Speter%token	IL_ICMP_TIMXCEED_REASS IL_ICMP_PARAMPROB IL_ICMP_PARAMPROB_OPTABSENT
20931183Speter%token	IL_ICMP_TSTAMP IL_ICMP_TSTAMPREPLY IL_ICMP_IREQ IL_ICMP_IREQREPLY
21031183Speter%token	IL_ICMP_MASKREQ IL_ICMP_MASKREPLY IL_ICMP_SEQ IL_ICMP_ID
21131183Speter%token	IL_ICMP_OTIME IL_ICMP_RTIME IL_ICMP_TTIME
21231183Speter
21331183Speter%%
21431183Speterfile:	line
21531183Speter	| line file
21631183Speter	| IL_COMMENT
21731183Speter	| IL_COMMENT file
21831183Speter	;
21931183Speter
22031183Speterline:	iface
22131183Speter	| arp
22231183Speter	| send
22331183Speter	| defrouter
22431183Speter	| ipline
22531183Speter	;
22631183Speter
22731183Speteriface:  ifhdr '{' ifaceopts '}' ';'	{ check_interface(); }
22831183Speter	;
22931183Speter
23031183Speterifhdr:	IL_INTERFACE			{ new_interface(); }
23131183Speter	;
23231183Speter
23331183Speterifaceopts:
23431183Speter	ifaceopt
23531183Speter	| ifaceopt ifaceopts
23631183Speter	;
23731183Speter
23831183Speterifaceopt:
23934739Speter	IL_IFNAME token			{ set_ifname(&$2); }
24034739Speter	| IL_MTU number			{ set_ifmtu($2); }
24134739Speter	| IL_V4ADDR token		{ set_ifv4addr(&$2); }
24234739Speter	| IL_EADDR token		{ set_ifeaddr(&$2); }
24331183Speter	;
24431183Speter
24531183Spetersend:   sendhdr '{' sendbody '}' ';'	{ packet_done(); }
24631183Speter	| sendhdr ';'			{ packet_done(); }
24731183Speter	;
24831183Speter
24931183Spetersendhdr:
25031183Speter	IL_SEND				{ reset_send(); }
25131183Speter	;
25231183Speter
25331183Spetersendbody:
25431183Speter	sendopt
25531183Speter	| sendbody sendopt
25631183Speter	;
25731183Speter
25831183Spetersendopt:
25934739Speter	IL_IFNAME token			{ set_sendif(&$2); }
26034739Speter	| IL_VIA token			{ set_sendvia(&$2); }
26131183Speter	;
26231183Speter
26331183Speterarp:    arphdr '{' arpbody '}' ';'
26431183Speter	;
26531183Speter
26631183Speterarphdr:	IL_ARP				{ new_arp(); }
26731183Speter	;
26831183Speter
26931183Speterarpbody:
27031183Speter	arpopt
27131183Speter	| arpbody arpopt
27231183Speter	;
27331183Speter
27434739Speterarpopt: IL_V4ADDR token			{ set_arpv4addr(&$2); }
27534739Speter	| IL_EADDR token		{ set_arpeaddr(&$2); }
27631183Speter	;
27731183Speter
27831183Speterdefrouter:
27934739Speter	IL_DEFROUTER token		{ set_defaultrouter(&$2); }
28031183Speter	;
28131183Speter
28231183Speterbodyline:
28331183Speter	ipline
28431183Speter	| tcp tcpline
28531183Speter	| udp udpline
28631183Speter	| icmp icmpline
28731183Speter	| data dataline
28831183Speter	;
28931183Speter
29031183Speteripline:	ipv4 '{' ipv4body '}' ';'	{ end_ipv4(); }
29131183Speter	;
29231183Speter
29331183Speteripv4:	IL_IPV4				{ new_packet(); }
29431183Speter
29531183Speteripv4body:
29631183Speter	ipv4type
29731183Speter	| ipv4type ipv4body
29831183Speter	| bodyline
29931183Speter	;
30031183Speter
30131183Speteripv4type:
30234739Speter	IL_V4PROTO token		{ set_ipv4proto(&$2); }
30334739Speter	| IL_V4SRC token		{ set_ipv4src(&$2); }
30434739Speter	| IL_V4DST token		{ set_ipv4dst(&$2); }
30534739Speter	| IL_V4OFF token		{ set_ipv4off(&$2); }
30634739Speter	| IL_V4V token			{ set_ipv4v(&$2); }
30734739Speter	| IL_V4HL token			{ set_ipv4hl(&$2); }
30834739Speter	| IL_V4ID token			{ set_ipv4id(&$2); }
30934739Speter	| IL_V4TTL token		{ set_ipv4ttl(&$2); }
31034739Speter	| IL_V4TOS token		{ set_ipv4tos(&$2); }
31134739Speter	| IL_V4SUM token		{ set_ipv4sum(&$2); }
31234739Speter	| IL_V4LEN token		{ set_ipv4len(&$2); }
31331183Speter	| ipv4opt '{' ipv4optlist '}' ';'	{ end_ipopt(); }
31431183Speter	;
31531183Speter
31631183Spetertcp:	IL_TCP				{ new_tcpheader(); }
31731183Speter	;
31831183Speter
31931183Spetertcpline:
32031183Speter	'{' tcpheader '}' ';'		{ end_tcp(); }
32131183Speter	;
32231183Speter
32331183Spetertcpheader:
32434739Speter	tcpbody
32534739Speter	| tcpbody tcpheader
32631183Speter	| bodyline
32731183Speter	;
32831183Speter
32931183Spetertcpbody:
33034739Speter	IL_SPORT token			{ set_tcpsport(&$2); }
33134739Speter	| IL_DPORT token		{ set_tcpdport(&$2); }
33234739Speter	| IL_TCPSEQ token		{ set_tcpseq(&$2); }
33334739Speter	| IL_TCPACK token		{ set_tcpack(&$2); }
33434739Speter	| IL_TCPOFF token		{ set_tcpoff(&$2); }
33534739Speter	| IL_TCPURP token		{ set_tcpurp(&$2); }
33634739Speter	| IL_TCPWIN token		{ set_tcpwin(&$2); }
33734739Speter	| IL_TCPSUM token		{ set_tcpsum(&$2); }
33834739Speter	| IL_TCPFL token		{ set_tcpflags(&$2); }
33931183Speter	| IL_TCPOPT '{' tcpopts '}' ';'	{ end_tcpopt(); }
34031183Speter	;
34131183Speter
34231183Spetertcpopts:
34331183Speter	| tcpopt tcpopts
34431183Speter	;
34531183Speter
34631183Spetertcpopt:	IL_TCPO_NOP ';'			{ set_tcpopt(IL_TCPO_NOP, NULL); }
34731183Speter	| IL_TCPO_EOL ';'		{ set_tcpopt(IL_TCPO_EOL, NULL); }
34834739Speter	| IL_TCPO_MSS optoken		{ set_tcpopt(IL_TCPO_MSS,&$2);}
34937074Speter	| IL_TCPO_WSCALE optoken	{ set_tcpopt(IL_TCPO_WSCALE,&$2);}
35034739Speter	| IL_TCPO_TS optoken		{ set_tcpopt(IL_TCPO_TS, &$2);}
35131183Speter	;
35231183Speter
35331183Speterudp:	IL_UDP				{ new_udpheader(); }
35431183Speter	;
35531183Speter
35631183Speterudpline:
35731183Speter	'{' udpheader '}' ';'		{ end_udp(); }
35831183Speter	;
35931183Speter
36031183Speter
36131183Speterudpheader:
36231183Speter	udpbody
36331183Speter	| udpbody udpheader
36431183Speter	| bodyline
36531183Speter	;
36631183Speter
36731183Speterudpbody:
36834739Speter	IL_SPORT token			{ set_tcpsport(&$2); }
36934739Speter	| IL_DPORT token		{ set_tcpdport(&$2); }
37034739Speter	| IL_UDPLEN token		{ set_udplen(&$2); }
37134739Speter	| IL_UDPSUM token		{ set_udpsum(&$2); }
37231183Speter	;
37331183Speter
37431183Spetericmp:	IL_ICMP				{ new_icmpheader(); }
37531183Speter	;
37631183Speter
37731183Spetericmpline:
37831183Speter	'{' icmpbody '}' ';'		{ end_icmp(); }
37931183Speter	;
38031183Speter
38131183Spetericmpbody:
38231183Speter	icmpheader
38331183Speter	| icmpheader bodyline
38431183Speter	;
38531183Speter
38631183Spetericmpheader:
38731183Speter	IL_ICMPTYPE icmptype
38831183Speter	| IL_ICMPTYPE icmptype icmpcode
38931183Speter	;
39031183Speter
39131183Spetericmpcode:
39234739Speter	IL_ICMPCODE token		{ set_icmpcodetok(&$2); }
39331183Speter	;
39431183Speter
39531183Spetericmptype:
39631183Speter	IL_ICMP_ECHOREPLY ';'		{ set_icmptype(ICMP_ECHOREPLY); }
39731183Speter	| IL_ICMP_ECHOREPLY '{' icmpechoopts '}' ';'
39831183Speter	| unreach
39931183Speter	| IL_ICMP_SOURCEQUENCH ';'	{ set_icmptype(ICMP_SOURCEQUENCH); }
40031183Speter	| redirect
40131183Speter	| IL_ICMP_ROUTERADVERT ';'	{ set_icmptype(ICMP_ROUTERADVERT); }
40231183Speter	| IL_ICMP_ROUTERSOLICIT ';'	{ set_icmptype(ICMP_ROUTERSOLICIT); }
40331183Speter	| IL_ICMP_ECHO ';'		{ set_icmptype(ICMP_ECHO); }
40431183Speter	| IL_ICMP_ECHO '{' icmpechoopts '}' ';'
40531183Speter	| IL_ICMP_TIMXCEED ';'		{ set_icmptype(ICMP_TIMXCEED); }
40631183Speter	| IL_ICMP_TIMXCEED '{' exceed '}' ';'
40731183Speter	| IL_ICMP_TSTAMP ';'		{ set_icmptype(ICMP_TSTAMP); }
40831183Speter	| IL_ICMP_TSTAMPREPLY ';'	{ set_icmptype(ICMP_TSTAMPREPLY); }
40931183Speter	| IL_ICMP_TSTAMPREPLY '{' icmptsopts '}' ';'
41031183Speter	| IL_ICMP_IREQ ';'		{ set_icmptype(ICMP_IREQ); }
41131183Speter	| IL_ICMP_IREQREPLY ';'		{ set_icmptype(ICMP_IREQREPLY); }
41231183Speter	| IL_ICMP_IREQREPLY '{' data dataline '}' ';'
41331183Speter	| IL_ICMP_MASKREQ ';'		{ set_icmptype(ICMP_MASKREQ); }
41431183Speter	| IL_ICMP_MASKREPLY ';'		{ set_icmptype(ICMP_MASKREPLY); }
41531183Speter	| IL_ICMP_MASKREPLY '{' token '}' ';'
41631183Speter	| IL_ICMP_PARAMPROB ';'		{ set_icmptype(ICMP_PARAMPROB); }
41731183Speter	| IL_ICMP_PARAMPROB '{' paramprob '}' ';'
41834739Speter	| IL_TOKEN ';'			{ set_icmptypetok(&$1); }
41931183Speter	;
42031183Speter
42131183Spetericmpechoopts:
42231183Speter	| icmpechoopts icmpecho
42331183Speter	;
42431183Speter
42531183Spetericmpecho:
42634739Speter	IL_ICMP_SEQ number 		{ set_icmpseq($2); }
42734739Speter	| IL_ICMP_ID number		{ set_icmpid($2); }
42831183Speter	;
42931183Speter
43031183Spetericmptsopts:
43131183Speter	| icmptsopts icmpts ';'
43231183Speter	;
43331183Speter
43434739Spetericmpts: IL_ICMP_OTIME number 		{ set_icmpotime($2); }
43534739Speter	| IL_ICMP_RTIME number 		{ set_icmprtime($2); }
43634739Speter	| IL_ICMP_TTIME number 		{ set_icmpttime($2); }
43731183Speter	;
43831183Speter
43931183Speterunreach:
44031183Speter	IL_ICMP_UNREACH
44131183Speter	| IL_ICMP_UNREACH '{' unreachopts '}' ';'
44231183Speter	;
44331183Speter
44431183Speterunreachopts:
44531183Speter	IL_ICMP_UNREACH_NET line
44631183Speter	| IL_ICMP_UNREACH_HOST line
44731183Speter	| IL_ICMP_UNREACH_PROTOCOL line
44831183Speter	| IL_ICMP_UNREACH_PORT line
44934739Speter	| IL_ICMP_UNREACH_NEEDFRAG number ';'	{ set_icmpmtu($2); }
45031183Speter	| IL_ICMP_UNREACH_SRCFAIL line
45131183Speter	| IL_ICMP_UNREACH_NET_UNKNOWN line
45231183Speter	| IL_ICMP_UNREACH_HOST_UNKNOWN line
45331183Speter	| IL_ICMP_UNREACH_ISOLATED line
45431183Speter	| IL_ICMP_UNREACH_NET_PROHIB line
45531183Speter	| IL_ICMP_UNREACH_HOST_PROHIB line
45631183Speter	| IL_ICMP_UNREACH_TOSNET line
45731183Speter	| IL_ICMP_UNREACH_TOSHOST line
45831183Speter	| IL_ICMP_UNREACH_FILTER_PROHIB line
45931183Speter	| IL_ICMP_UNREACH_HOST_PRECEDENCE line
46031183Speter	| IL_ICMP_UNREACH_PRECEDENCE_CUTOFF line
46131183Speter	;
46231183Speter
46331183Speterredirect:
46431183Speter	IL_ICMP_REDIRECT
46531183Speter	| IL_ICMP_REDIRECT '{' redirectopts '}' ';'
46631183Speter	;
46731183Speter
46831183Speterredirectopts:
46934739Speter	| IL_ICMP_REDIRECT_NET token		{ set_redir(0, &$2); }
47034739Speter	| IL_ICMP_REDIRECT_HOST token		{ set_redir(1, &$2); }
47134739Speter	| IL_ICMP_REDIRECT_TOSNET token		{ set_redir(2, &$2); }
47234739Speter	| IL_ICMP_REDIRECT_TOSHOST token	{ set_redir(3, &$2); }
47331183Speter	;
47431183Speter
47531183Speterexceed:
47631183Speter	IL_ICMP_TIMXCEED_INTRANS line
47731183Speter	| IL_ICMP_TIMXCEED_REASS line
47831183Speter	;
47931183Speter
48031183Speterparamprob:
48131183Speter	IL_ICMP_PARAMPROB_OPTABSENT
48231183Speter	| IL_ICMP_PARAMPROB_OPTABSENT paraprobarg
48331183Speter
48431183Speterparaprobarg:
48534739Speter	'{' number '}' ';'		{ set_icmppprob($2); }
48631183Speter	;
48731183Speter
48831183Speteripv4opt:	IL_V4OPT		{ new_ipv4opt(); }
48931183Speter	;
49031183Speter
49131183Speteripv4optlist:
49231183Speter	| ipv4opts ipv4optlist
49331183Speter	;
49431183Speter
49531183Speteripv4opts:
49631183Speter	IL_IPO_NOP ';'			{ add_ipopt(IL_IPO_NOP, NULL); }
49734739Speter	| IL_IPO_RR optnumber		{ add_ipopt(IL_IPO_RR, &$2); }
49831183Speter	| IL_IPO_ZSU ';'		{ add_ipopt(IL_IPO_ZSU, NULL); }
49931183Speter	| IL_IPO_MTUP ';'		{ add_ipopt(IL_IPO_MTUP, NULL); }
50031183Speter	| IL_IPO_MTUR ';'		{ add_ipopt(IL_IPO_MTUR, NULL); }
50131183Speter	| IL_IPO_ENCODE ';'		{ add_ipopt(IL_IPO_ENCODE, NULL); }
50231183Speter	| IL_IPO_TS ';'			{ add_ipopt(IL_IPO_TS, NULL); }
50331183Speter	| IL_IPO_TR ';'			{ add_ipopt(IL_IPO_TR, NULL); }
50431183Speter	| IL_IPO_SEC ';'		{ add_ipopt(IL_IPO_SEC, NULL); }
50531183Speter	| IL_IPO_SECCLASS secclass	{ add_ipopt(IL_IPO_SECCLASS, sclass); }
50634739Speter	| IL_IPO_LSRR token		{ add_ipopt(IL_IPO_LSRR,&$2); }
50731183Speter	| IL_IPO_ESEC ';'		{ add_ipopt(IL_IPO_ESEC, NULL); }
50831183Speter	| IL_IPO_CIPSO ';'		{ add_ipopt(IL_IPO_CIPSO, NULL); }
50934739Speter	| IL_IPO_SATID optnumber	{ add_ipopt(IL_IPO_SATID,&$2);}
51034739Speter	| IL_IPO_SSRR token		{ add_ipopt(IL_IPO_SSRR,&$2); }
51131183Speter	| IL_IPO_ADDEXT ';'		{ add_ipopt(IL_IPO_ADDEXT, NULL); }
51231183Speter	| IL_IPO_VISA ';'		{ add_ipopt(IL_IPO_VISA, NULL); }
51331183Speter	| IL_IPO_IMITD ';'		{ add_ipopt(IL_IPO_IMITD, NULL); }
51431183Speter	| IL_IPO_EIP ';'		{ add_ipopt(IL_IPO_EIP, NULL); }
51531183Speter	| IL_IPO_FINN ';'		{ add_ipopt(IL_IPO_FINN, NULL); }
51631183Speter	;
51731183Speter
51831183Spetersecclass:
51934739Speter	IL_IPS_RESERV4 ';'		{ set_secclass(&$1); }
52034739Speter	| IL_IPS_TOPSECRET ';'		{ set_secclass(&$1); }
52134739Speter	| IL_IPS_SECRET ';'		{ set_secclass(&$1); }
52234739Speter	| IL_IPS_RESERV3 ';'		{ set_secclass(&$1); }
52334739Speter	| IL_IPS_CONFID ';'		{ set_secclass(&$1); }
52434739Speter	| IL_IPS_UNCLASS ';'		{ set_secclass(&$1); }
52534739Speter	| IL_IPS_RESERV2 ';'		{ set_secclass(&$1); }
52634739Speter	| IL_IPS_RESERV1 ';'		{ set_secclass(&$1); }
52731183Speter	;
52831183Speter
52931183Speterdata:	IL_DATA				{ new_data(); }
53031183Speter	;
53131183Speter
53231183Speterdataline:
53331183Speter	'{' databody '}' ';'		{ end_data(); }
53431183Speter	;
53531183Speter
53631183Speterdatabody: dataopts
53731183Speter	| dataopts databody
53831183Speter	;
53931183Speter
54031183Speterdataopts:
54134739Speter	IL_DLEN token			{ set_datalen(&$2); }
54234739Speter	| IL_DVALUE token 		{ set_data(&$2); }
54334739Speter	| IL_DFILE token 		{ set_datafile(&$2); }
54431183Speter	;
54531183Speter
54631183Spetertoken: IL_TOKEN ';'
54731183Speter	;
54831183Speter
54931183Speteroptoken: ';'				{ $$ = ""; }
55031183Speter	| token
55131183Speter	;
55231183Speter
55331183Speternumber: digits ';'
55431183Speter	;
55531183Speter
55631183Speteroptnumber: ';'				{ $$ = 0; }
55731183Speter	| number
55831183Speter	;
55931183Speter
56031183Speterdigits:	IL_NUMBER
56131183Speter	| digits IL_NUMBER
56231183Speter	;
56331183Speter%%
56431183Speter
56531183Speterstruct	statetoopt	toipopts[] = {
56631183Speter	{ IL_IPO_NOP,		IPOPT_NOP },
56731183Speter	{ IL_IPO_RR,		IPOPT_RR },
56831183Speter	{ IL_IPO_ZSU,		IPOPT_ZSU },
56931183Speter	{ IL_IPO_MTUP,		IPOPT_MTUP },
57031183Speter	{ IL_IPO_MTUR,		IPOPT_MTUR },
57131183Speter	{ IL_IPO_ENCODE,	IPOPT_ENCODE },
57231183Speter	{ IL_IPO_TS,		IPOPT_TS },
57331183Speter	{ IL_IPO_TR,		IPOPT_TR },
57431183Speter	{ IL_IPO_SEC,		IPOPT_SECURITY },
57531183Speter	{ IL_IPO_SECCLASS,	IPOPT_SECURITY },
57631183Speter	{ IL_IPO_LSRR,		IPOPT_LSRR },
57731183Speter	{ IL_IPO_ESEC,		IPOPT_E_SEC },
57831183Speter	{ IL_IPO_CIPSO,		IPOPT_CIPSO },
57931183Speter	{ IL_IPO_SATID,		IPOPT_SATID },
58031183Speter	{ IL_IPO_SSRR,		IPOPT_SSRR },
58131183Speter	{ IL_IPO_ADDEXT,	IPOPT_ADDEXT },
58231183Speter	{ IL_IPO_VISA,		IPOPT_VISA },
58331183Speter	{ IL_IPO_IMITD,		IPOPT_IMITD },
58431183Speter	{ IL_IPO_EIP,		IPOPT_EIP },
58531183Speter	{ IL_IPO_FINN,		IPOPT_FINN },
58631183Speter	{ 0, 0 }
58731183Speter};
58831183Speter
58931183Speterstruct	statetoopt	tosecopts[] = {
59031183Speter	{ IL_IPS_RESERV4,	IPSO_CLASS_RES4 },
59131183Speter	{ IL_IPS_TOPSECRET,	IPSO_CLASS_TOPS },
59231183Speter	{ IL_IPS_SECRET,	IPSO_CLASS_SECR },
59331183Speter	{ IL_IPS_RESERV3,	IPSO_CLASS_RES3 },
59431183Speter	{ IL_IPS_CONFID,	IPSO_CLASS_CONF },
59531183Speter	{ IL_IPS_UNCLASS,	IPSO_CLASS_UNCL },
59631183Speter	{ IL_IPS_RESERV2,	IPSO_CLASS_RES2 },
59731183Speter	{ IL_IPS_RESERV1,	IPSO_CLASS_RES1 },
59831183Speter	{ 0, 0 }
59931183Speter};
60031183Speter
60131183Speter#ifdef	bsdi
60231183Speterstruct ether_addr *
60331183Speterether_aton(s)
604255332Scy	char *s;
60531183Speter{
60631183Speter	static struct ether_addr n;
60731183Speter	u_int i[6];
60831183Speter
60931183Speter	if (sscanf(s, " %x:%x:%x:%x:%x:%x ", &i[0], &i[1],
61031183Speter	    &i[2], &i[3], &i[4], &i[5]) == 6) {
61131183Speter		n.ether_addr_octet[0] = (u_char)i[0];
61231183Speter		n.ether_addr_octet[1] = (u_char)i[1];
61331183Speter		n.ether_addr_octet[2] = (u_char)i[2];
61431183Speter		n.ether_addr_octet[3] = (u_char)i[3];
61531183Speter		n.ether_addr_octet[4] = (u_char)i[4];
61631183Speter		n.ether_addr_octet[5] = (u_char)i[5];
61731183Speter		return &n;
61831183Speter	}
61931183Speter	return NULL;
62031183Speter}
62131183Speter#endif
62231183Speter
62331183Speter
62431183Speterstruct in_addr getipv4addr(arg)
62531183Speterchar *arg;
62631183Speter{
62731183Speter	struct hostent *hp;
62831183Speter	struct in_addr in;
62931183Speter
63031183Speter	in.s_addr = 0xffffffff;
63131183Speter
63231183Speter	if ((hp = gethostbyname(arg)))
63331183Speter		bcopy(hp->h_addr, &in.s_addr, sizeof(struct in_addr));
63431183Speter	else
63531183Speter		in.s_addr = inet_addr(arg);
63631183Speter	return in;
63731183Speter}
63831183Speter
63931183Speter
64031183Speteru_short getportnum(pr, name)
64131183Speterchar *pr, *name;
64231183Speter{
64331183Speter	struct servent *sp;
64431183Speter
64531183Speter	if (!(sp = getservbyname(name, pr)))
64634739Speter		return htons(atoi(name));
64731183Speter	return sp->s_port;
64831183Speter}
64931183Speter
65031183Speter
65131183Speterstruct ether_addr *geteaddr(arg, buf)
65231183Speterchar *arg;
65331183Speterstruct ether_addr *buf;
65431183Speter{
65531183Speter	struct ether_addr *e;
65631183Speter
65731183Speter#if !defined(hpux) && !defined(linux)
65831183Speter	e = ether_aton(arg);
65931183Speter	if (!e)
66031183Speter		fprintf(stderr, "Invalid ethernet address: %s\n", arg);
66131183Speter	else
66231183Speter# ifdef	__FreeBSD__
66331183Speter		bcopy(e->octet, buf->octet, sizeof(e->octet));
66431183Speter# else
66531183Speter		bcopy(e->ether_addr_octet, buf->ether_addr_octet,
66631183Speter		      sizeof(e->ether_addr_octet));
66731183Speter# endif
66831183Speter	return e;
66931183Speter#else
67031183Speter	return NULL;
67131183Speter#endif
67231183Speter}
67331183Speter
67431183Speter
67531183Spetervoid *new_header(type)
67631183Speterint type;
67731183Speter{
67831183Speter	aniphdr_t *aip, *oip = canip;
67931183Speter	int	sz = 0;
68031183Speter
68131183Speter	aip = (aniphdr_t *)calloc(1, sizeof(*aip));
68231183Speter	*aniptail = aip;
68331183Speter	aniptail = &aip->ah_next;
68431183Speter	aip->ah_p = type;
68531183Speter	aip->ah_prev = oip;
68631183Speter	canip = aip;
68731183Speter
68831183Speter	if (type == IPPROTO_UDP)
68931183Speter		sz = sizeof(udphdr_t);
69031183Speter	else if (type == IPPROTO_TCP)
69131183Speter		sz = sizeof(tcphdr_t);
69231183Speter	else if (type == IPPROTO_ICMP)
69331183Speter		sz = sizeof(icmphdr_t);
69431183Speter	else if (type == IPPROTO_IP)
69531183Speter		sz = sizeof(ip_t);
69631183Speter
69731183Speter	if (oip)
69831183Speter		canip->ah_data = oip->ah_data + oip->ah_len;
69931183Speter	else
70031183Speter		canip->ah_data = (char *)ipbuffer;
70131183Speter
70231183Speter	/*
70331183Speter	 * Increase the size fields in all wrapping headers.
70431183Speter	 */
70531183Speter	for (aip = aniphead; aip; aip = aip->ah_next) {
70631183Speter		aip->ah_len += sz;
70731183Speter		if (aip->ah_p == IPPROTO_IP)
70831183Speter			aip->ah_ip->ip_len += sz;
70931183Speter		else if (aip->ah_p == IPPROTO_UDP)
71031183Speter			aip->ah_udp->uh_ulen += sz;
71131183Speter	}
71231183Speter	return (void *)canip->ah_data;
71331183Speter}
71431183Speter
71531183Speter
71631183Spetervoid free_aniplist()
71731183Speter{
71831183Speter	aniphdr_t *aip, **aipp = &aniphead;
71931183Speter
72031183Speter	while ((aip = *aipp)) {
72131183Speter		*aipp = aip->ah_next;
72231183Speter		free(aip);
72331183Speter	}
72431183Speter	aniptail = &aniphead;
72531183Speter}
72631183Speter
72731183Speter
72831183Spetervoid inc_anipheaders(inc)
72931183Speterint inc;
73031183Speter{
73131183Speter	aniphdr_t *aip;
73231183Speter
73331183Speter	for (aip = aniphead; aip; aip = aip->ah_next) {
73431183Speter		aip->ah_len += inc;
73531183Speter		if (aip->ah_p == IPPROTO_IP)
73631183Speter			aip->ah_ip->ip_len += inc;
73731183Speter		else if (aip->ah_p == IPPROTO_UDP)
73831183Speter			aip->ah_udp->uh_ulen += inc;
73931183Speter	}
74031183Speter}
74131183Speter
74231183Speter
74331183Spetervoid new_data()
74431183Speter{
74531183Speter	(void) new_header(-1);
74631183Speter	canip->ah_len = 0;
74731183Speter}
74831183Speter
74931183Speter
75031183Spetervoid set_datalen(arg)
75131183Speterchar **arg;
75231183Speter{
75331183Speter	int	len;
75431183Speter
75531183Speter	len = strtol(*arg, NULL, 0);
75631183Speter	inc_anipheaders(len);
75731183Speter	free(*arg);
75831183Speter	*arg = NULL;
75931183Speter}
76031183Speter
76131183Speter
76231183Spetervoid set_data(arg)
76331183Speterchar **arg;
76431183Speter{
76531183Speter	u_char *s = (u_char *)*arg, *t = (u_char *)canip->ah_data, c;
76631183Speter	int len = 0, todo = 0, quote = 0, val = 0;
76731183Speter
76831183Speter	while ((c = *s++)) {
76931183Speter		if (todo) {
770145519Sdarrenr			if (ISDIGIT(c)) {
77131183Speter				todo--;
77231183Speter				if (c > '7') {
77331183Speter					fprintf(stderr, "octal with %c!\n", c);
77431183Speter					break;
77531183Speter				}
77631183Speter				val <<= 3;
77731183Speter				val |= (c - '0');
77831183Speter			}
779145519Sdarrenr			if (!ISDIGIT(c) || !todo) {
78031183Speter				*t++ = (u_char)(val & 0xff);
78131183Speter				todo = 0;
78231183Speter			}
78337074Speter			if (todo)
78437074Speter				continue;
78531183Speter		}
78631183Speter		if (quote) {
787145519Sdarrenr			if (ISDIGIT(c)) {
78831183Speter				todo = 2;
78931183Speter				if (c > '7') {
79031183Speter					fprintf(stderr, "octal with %c!\n", c);
79131183Speter					break;
79231183Speter				}
79331183Speter				val = (c - '0');
79431183Speter			} else {
79531183Speter				switch (c)
79631183Speter				{
79731183Speter				case '\"' :
79831183Speter					*t++ = '\"';
79931183Speter					break;
80031183Speter				case '\\' :
80131183Speter					*t++ = '\\';
80231183Speter					break;
80331183Speter				case 'n' :
80431183Speter					*t++ = '\n';
80531183Speter					break;
80631183Speter				case 'r' :
80731183Speter					*t++ = '\r';
80831183Speter					break;
80931183Speter				case 't' :
81031183Speter					*t++ = '\t';
81131183Speter					break;
81231183Speter				}
81331183Speter			}
81437074Speter			quote = 0;
81531183Speter			continue;
81631183Speter		}
81731183Speter
81831183Speter		if (c == '\\')
81931183Speter			quote = 1;
82031183Speter		else
82131183Speter			*t++ = c;
82231183Speter	}
82337074Speter	if (todo)
82437074Speter		*t++ = (u_char)(val & 0xff);
82531183Speter	if (quote)
82631183Speter		*t++ = '\\';
82731183Speter	len = t - (u_char *)canip->ah_data;
82831183Speter	inc_anipheaders(len - canip->ah_len);
82931183Speter	canip->ah_len = len;
83031183Speter}
83131183Speter
83231183Speter
83331183Spetervoid set_datafile(arg)
83431183Speterchar **arg;
83531183Speter{
83631183Speter	struct stat sb;
83731183Speter	char *file = *arg;
83831183Speter	int fd, len;
83931183Speter
84031183Speter	if ((fd = open(file, O_RDONLY)) == -1) {
84131183Speter		perror("open");
84231183Speter		exit(-1);
84331183Speter	}
84431183Speter
84531183Speter	if (fstat(fd, &sb) == -1) {
84631183Speter		perror("fstat");
84731183Speter		exit(-1);
84831183Speter	}
84931183Speter
85031183Speter	if ((sb.st_size + aniphead->ah_len ) > 65535) {
85131183Speter		fprintf(stderr, "data file %s too big to include.\n", file);
85231183Speter		close(fd);
85331183Speter		return;
85431183Speter	}
85531183Speter	if ((len = read(fd, canip->ah_data, sb.st_size)) == -1) {
85631183Speter		perror("read");
85731183Speter		close(fd);
85831183Speter		return;
85931183Speter	}
86031183Speter	inc_anipheaders(len);
86131183Speter	canip->ah_len += len;
86231183Speter	close(fd);
86331183Speter}
86431183Speter
86531183Speter
86631183Spetervoid new_packet()
86731183Speter{
86831183Speter	static	u_short	id = 0;
86931183Speter
87031183Speter	if (!aniphead)
87131183Speter		bzero((char *)ipbuffer, sizeof(ipbuffer));
87231183Speter
87331183Speter	ip = (ip_t *)new_header(IPPROTO_IP);
87431183Speter	ip->ip_v = IPVERSION;
87531183Speter	ip->ip_hl = sizeof(ip_t) >> 2;
87631183Speter	ip->ip_len = sizeof(ip_t);
87731183Speter	ip->ip_ttl = 63;
87831183Speter	ip->ip_id = htons(id++);
87931183Speter}
88031183Speter
88131183Speter
88231183Spetervoid set_ipv4proto(arg)
88331183Speterchar **arg;
88431183Speter{
88531183Speter	struct protoent *pr;
88631183Speter
88731183Speter	if ((pr = getprotobyname(*arg)))
88831183Speter		ip->ip_p = pr->p_proto;
88931183Speter	else
89031183Speter		if (!(ip->ip_p = atoi(*arg)))
89131183Speter			fprintf(stderr, "unknown protocol %s\n", *arg);
89231183Speter	free(*arg);
89331183Speter	*arg = NULL;
89431183Speter}
89531183Speter
89631183Speter
89731183Spetervoid set_ipv4src(arg)
89831183Speterchar **arg;
89931183Speter{
90031183Speter	ip->ip_src = getipv4addr(*arg);
90131183Speter	free(*arg);
90231183Speter	*arg = NULL;
90331183Speter}
90431183Speter
90531183Speter
90631183Spetervoid set_ipv4dst(arg)
90731183Speterchar **arg;
90831183Speter{
90931183Speter	ip->ip_dst = getipv4addr(*arg);
91031183Speter	free(*arg);
91131183Speter	*arg = NULL;
91231183Speter}
91331183Speter
91431183Speter
91531183Spetervoid set_ipv4off(arg)
91631183Speterchar **arg;
91731183Speter{
91837074Speter	ip->ip_off = htons(strtol(*arg, NULL, 0));
91931183Speter	free(*arg);
92031183Speter	*arg = NULL;
92131183Speter}
92231183Speter
92331183Speter
92431183Spetervoid set_ipv4v(arg)
92531183Speterchar **arg;
92631183Speter{
92731183Speter	ip->ip_v = strtol(*arg, NULL, 0);
92831183Speter	free(*arg);
92931183Speter	*arg = NULL;
93031183Speter}
93131183Speter
93231183Speter
93331183Spetervoid set_ipv4hl(arg)
93431183Speterchar **arg;
93531183Speter{
93631183Speter	int newhl, inc;
93731183Speter
93831183Speter	newhl = strtol(*arg, NULL, 0);
93931183Speter	inc = (newhl - ip->ip_hl) << 2;
94031183Speter	ip->ip_len += inc;
94131183Speter	ip->ip_hl = newhl;
94231183Speter	canip->ah_len += inc;
94331183Speter	free(*arg);
94431183Speter	*arg = NULL;
94531183Speter}
94631183Speter
94731183Speter
94831183Spetervoid set_ipv4ttl(arg)
94931183Speterchar **arg;
95031183Speter{
95131183Speter	ip->ip_ttl = strtol(*arg, NULL, 0);
95231183Speter	free(*arg);
95331183Speter	*arg = NULL;
95431183Speter}
95531183Speter
95631183Speter
95731183Spetervoid set_ipv4tos(arg)
95831183Speterchar **arg;
95931183Speter{
96031183Speter	ip->ip_tos = strtol(*arg, NULL, 0);
96131183Speter	free(*arg);
96231183Speter	*arg = NULL;
96331183Speter}
96431183Speter
96531183Speter
96631183Spetervoid set_ipv4id(arg)
96731183Speterchar **arg;
96831183Speter{
96937074Speter	ip->ip_id = htons(strtol(*arg, NULL, 0));
97031183Speter	free(*arg);
97131183Speter	*arg = NULL;
97231183Speter}
97331183Speter
97431183Speter
97531183Spetervoid set_ipv4sum(arg)
97631183Speterchar **arg;
97731183Speter{
97831183Speter	ip->ip_sum = strtol(*arg, NULL, 0);
97931183Speter	free(*arg);
98031183Speter	*arg = NULL;
98131183Speter}
98231183Speter
98331183Speter
98431183Spetervoid set_ipv4len(arg)
98531183Speterchar **arg;
98631183Speter{
98731183Speter	int len;
98831183Speter
98931183Speter	len = strtol(*arg, NULL, 0);
99031183Speter	inc_anipheaders(len - ip->ip_len);
99131183Speter	ip->ip_len = len;
99231183Speter	free(*arg);
99331183Speter	*arg = NULL;
99431183Speter}
99531183Speter
99631183Speter
99731183Spetervoid new_tcpheader()
99831183Speter{
99931183Speter
100031183Speter	if ((ip->ip_p) && (ip->ip_p != IPPROTO_TCP)) {
100131183Speter		fprintf(stderr, "protocol %d specified with TCP!\n", ip->ip_p);
100231183Speter		return;
100331183Speter	}
100431183Speter	ip->ip_p = IPPROTO_TCP;
100531183Speter
100631183Speter	tcp = (tcphdr_t *)new_header(IPPROTO_TCP);
100737074Speter	tcp->th_win = htons(4096);
100831183Speter	tcp->th_off = sizeof(*tcp) >> 2;
100931183Speter}
101031183Speter
101131183Speter
101231183Spetervoid set_tcpsport(arg)
101331183Speterchar **arg;
101431183Speter{
101531183Speter	u_short *port;
101631183Speter	char *pr;
101731183Speter
101831183Speter	if (ip->ip_p == IPPROTO_UDP) {
101931183Speter		port = &udp->uh_sport;
102031183Speter		pr = "udp";
102131183Speter	} else {
102231183Speter		port = &tcp->th_sport;
102331183Speter		pr = "udp";
102431183Speter	}
102531183Speter
102631183Speter	*port = getportnum(pr, *arg);
102731183Speter	free(*arg);
102831183Speter	*arg = NULL;
102931183Speter}
103031183Speter
103131183Speter
103231183Spetervoid set_tcpdport(arg)
103331183Speterchar **arg;
103431183Speter{
103531183Speter	u_short *port;
103631183Speter	char *pr;
103731183Speter
103831183Speter	if (ip->ip_p == IPPROTO_UDP) {
103931183Speter		port = &udp->uh_dport;
104031183Speter		pr = "udp";
104131183Speter	} else {
104231183Speter		port = &tcp->th_dport;
104331183Speter		pr = "udp";
104431183Speter	}
104531183Speter
104631183Speter	*port = getportnum(pr, *arg);
104731183Speter	free(*arg);
104831183Speter	*arg = NULL;
104931183Speter}
105031183Speter
105131183Speter
105231183Spetervoid set_tcpseq(arg)
105331183Speterchar **arg;
105431183Speter{
105537074Speter	tcp->th_seq = htonl(strtol(*arg, NULL, 0));
105631183Speter	free(*arg);
105731183Speter	*arg = NULL;
105831183Speter}
105931183Speter
106031183Speter
106131183Spetervoid set_tcpack(arg)
106231183Speterchar **arg;
106331183Speter{
106437074Speter	tcp->th_ack = htonl(strtol(*arg, NULL, 0));
106531183Speter	free(*arg);
106631183Speter	*arg = NULL;
106731183Speter}
106831183Speter
106931183Speter
107031183Spetervoid set_tcpoff(arg)
107131183Speterchar **arg;
107231183Speter{
107331183Speter	int	off;
107431183Speter
107531183Speter	off = strtol(*arg, NULL, 0);
107631183Speter	inc_anipheaders((off - tcp->th_off) << 2);
107731183Speter	tcp->th_off = off;
107831183Speter	free(*arg);
107931183Speter	*arg = NULL;
108031183Speter}
108131183Speter
108231183Speter
108331183Spetervoid set_tcpurp(arg)
108431183Speterchar **arg;
108531183Speter{
108637074Speter	tcp->th_urp = htons(strtol(*arg, NULL, 0));
108731183Speter	free(*arg);
108831183Speter	*arg = NULL;
108931183Speter}
109031183Speter
109131183Speter
109231183Spetervoid set_tcpwin(arg)
109331183Speterchar **arg;
109431183Speter{
109537074Speter	tcp->th_win = htons(strtol(*arg, NULL, 0));
109631183Speter	free(*arg);
109731183Speter	*arg = NULL;
109831183Speter}
109931183Speter
110031183Speter
110131183Spetervoid set_tcpsum(arg)
110231183Speterchar **arg;
110331183Speter{
110431183Speter	tcp->th_sum = strtol(*arg, NULL, 0);
110531183Speter	free(*arg);
110631183Speter	*arg = NULL;
110731183Speter}
110831183Speter
110931183Speter
111031183Spetervoid set_tcpflags(arg)
111131183Speterchar **arg;
111231183Speter{
111331183Speter	static	char	flags[] = "ASURPF";
111431183Speter	static	int	flagv[] = { TH_ACK, TH_SYN, TH_URG, TH_RST, TH_PUSH,
111531183Speter				    TH_FIN } ;
111631183Speter	char *s, *t;
111731183Speter
111831183Speter	for (s = *arg; *s; s++)
111931183Speter		if (!(t = strchr(flags, *s))) {
112031183Speter			if (s - *arg) {
112131183Speter				fprintf(stderr, "unknown TCP flag %c\n", *s);
112231183Speter				break;
112331183Speter			}
112431183Speter			tcp->th_flags = strtol(*arg, NULL, 0);
112531183Speter			break;
112631183Speter		} else
112731183Speter			tcp->th_flags |= flagv[t - flags];
112831183Speter	free(*arg);
112931183Speter	*arg = NULL;
113031183Speter}
113131183Speter
113231183Speter
113331183Spetervoid set_tcpopt(state, arg)
113431183Speterint state;
113531183Speterchar **arg;
113631183Speter{
113731183Speter	u_char *s;
113831183Speter	int val, len, val2, pad, optval;
113931183Speter
114031183Speter	if (arg && *arg)
114131183Speter		val = atoi(*arg);
114231183Speter	else
114331183Speter		val = 0;
114431183Speter
114531183Speter	s = (u_char *)tcp + sizeof(*tcp) + canip->ah_optlen;
114631183Speter	switch (state)
114731183Speter	{
114831183Speter	case IL_TCPO_EOL :
114931183Speter		optval = 0;
115031183Speter		len = 1;
115131183Speter		break;
115231183Speter	case IL_TCPO_NOP :
115331183Speter		optval = 1;
115431183Speter		len = 1;
115531183Speter		break;
115631183Speter	case IL_TCPO_MSS :
115731183Speter		optval = 2;
115831183Speter		len = 4;
115931183Speter		break;
116031183Speter	case IL_TCPO_WSCALE :
116131183Speter		optval = 3;
116231183Speter		len = 3;
116331183Speter		break;
116431183Speter	case IL_TCPO_TS :
116531183Speter		optval = 8;
116631183Speter		len = 10;
116731183Speter		break;
116831183Speter	default :
116931183Speter		optval = 0;
117031183Speter		len = 0;
117131183Speter		break;
117231183Speter	}
117331183Speter
117431183Speter	if (len > 1) {
117531183Speter		/*
117631183Speter		 * prepend padding - if required.
117731183Speter		 */
117831183Speter		if (len & 3)
117931183Speter			for (pad = 4 - (len & 3); pad; pad--) {
118031183Speter				*s++ = 1;
118131183Speter				canip->ah_optlen++;
118231183Speter			}
118331183Speter		/*
118431183Speter		 * build tcp option
118531183Speter		 */
118631183Speter		*s++ = (u_char)optval;
118731183Speter		*s++ = (u_char)len;
118831183Speter		if (len > 2) {
118931183Speter			if (len == 3) {		/* 1 byte - char */
119031183Speter				*s++ = (u_char)val;
119131183Speter			} else if (len == 4) {	/* 2 bytes - short */
119231183Speter				*s++ = (u_char)((val >> 8) & 0xff);
119331183Speter				*s++ = (u_char)(val & 0xff);
119431183Speter			} else if (len >= 6) {	/* 4 bytes - long */
119531183Speter				val2 = htonl(val);
119631183Speter				bcopy((char *)&val2, s, 4);
119731183Speter			}
119831183Speter			s += (len - 2);
119931183Speter		}
120031183Speter	} else
120131183Speter		*s++ = (u_char)optval;
120231183Speter
120331183Speter	canip->ah_lastopt = optval;
120431183Speter	canip->ah_optlen += len;
120531183Speter
120631183Speter	if (arg && *arg) {
120731183Speter		free(*arg);
120831183Speter		*arg = NULL;
120931183Speter	}
121031183Speter}
121131183Speter
121231183Speter
121331183Spetervoid end_tcpopt()
121431183Speter{
121531183Speter	int pad;
121631183Speter	char *s = (char *)tcp;
121731183Speter
121831183Speter	s += sizeof(*tcp) + canip->ah_optlen;
121931183Speter	/*
122031183Speter	 * pad out so that we have a multiple of 4 bytes in size fo the
122131183Speter	 * options.  make sure last byte is EOL.
122231183Speter	 */
122331183Speter	if (canip->ah_optlen & 3) {
122431183Speter		if (canip->ah_lastopt != 1) {
122531183Speter			for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) {
122631183Speter				*s++ = 1;
122731183Speter				canip->ah_optlen++;
122831183Speter			}
122931183Speter			canip->ah_optlen++;
123031183Speter		} else {
123131183Speter			s -= 1;
123231183Speter
123331183Speter			for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) {
123431183Speter				*s++ = 1;
123531183Speter				canip->ah_optlen++;
123631183Speter			}
123731183Speter		}
123831183Speter		*s++ = 0;
123931183Speter	}
124031183Speter	tcp->th_off = (sizeof(*tcp) + canip->ah_optlen) >> 2;
124131183Speter	inc_anipheaders(canip->ah_optlen);
124231183Speter}
124331183Speter
124431183Speter
124531183Spetervoid new_udpheader()
124631183Speter{
124731183Speter	if ((ip->ip_p) && (ip->ip_p != IPPROTO_UDP)) {
124831183Speter		fprintf(stderr, "protocol %d specified with UDP!\n", ip->ip_p);
124931183Speter		return;
125031183Speter	}
125131183Speter	ip->ip_p = IPPROTO_UDP;
125231183Speter
125331183Speter	udp = (udphdr_t *)new_header(IPPROTO_UDP);
125431183Speter	udp->uh_ulen = sizeof(*udp);
125531183Speter}
125631183Speter
125731183Speter
125831183Spetervoid set_udplen(arg)
125931183Speterchar **arg;
126031183Speter{
126131183Speter	int len;
126231183Speter
126331183Speter	len = strtol(*arg, NULL, 0);
126431183Speter	inc_anipheaders(len - udp->uh_ulen);
126531183Speter	udp->uh_ulen = len;
126631183Speter	free(*arg);
126731183Speter	*arg = NULL;
126831183Speter}
126931183Speter
127031183Speter
127131183Spetervoid set_udpsum(arg)
127231183Speterchar **arg;
127331183Speter{
127431183Speter	udp->uh_sum = strtol(*arg, NULL, 0);
127531183Speter	free(*arg);
127631183Speter	*arg = NULL;
127731183Speter}
127831183Speter
127931183Speter
128031183Spetervoid prep_packet()
128131183Speter{
128231183Speter	iface_t *ifp;
128331183Speter	struct in_addr gwip;
128431183Speter
128531183Speter	ifp = sending.snd_if;
128631183Speter	if (!ifp) {
128731183Speter		fprintf(stderr, "no interface defined for sending!\n");
128831183Speter		return;
128931183Speter	}
129031183Speter	if (ifp->if_fd == -1)
1291145519Sdarrenr		ifp->if_fd = initdevice(ifp->if_name, 5);
129231183Speter	gwip = sending.snd_gw;
1293153881Sguido	if (!gwip.s_addr) {
1294153881Sguido		if (aniphead == NULL) {
1295153881Sguido			fprintf(stderr,
1296153881Sguido				"no destination address defined for sending\n");
1297153881Sguido			return;
1298153881Sguido		}
129931183Speter		gwip = aniphead->ah_ip->ip_dst;
1300153881Sguido	}
130131183Speter	(void) send_ip(ifp->if_fd, ifp->if_MTU, (ip_t *)ipbuffer, gwip, 2);
130231183Speter}
130331183Speter
130431183Speter
130531183Spetervoid packet_done()
130631183Speter{
130731183Speter	char    outline[80];
130831183Speter	int     i, j, k;
130931183Speter	u_char  *s = (u_char *)ipbuffer, *t = (u_char *)outline;
131031183Speter
131131183Speter	if (opts & OPT_VERBOSE) {
131237074Speter		ip->ip_len = htons(ip->ip_len);
131337074Speter		for (i = ntohs(ip->ip_len), j = 0; i; i--, j++, s++) {
131431183Speter			if (j && !(j & 0xf)) {
131531183Speter				*t++ = '\n';
131631183Speter				*t = '\0';
131731183Speter				fputs(outline, stdout);
131831183Speter				fflush(stdout);
131931183Speter				t = (u_char *)outline;
132031183Speter				*t = '\0';
132131183Speter			}
132231183Speter			sprintf((char *)t, "%02x", *s & 0xff);
132331183Speter			t += 2;
132431183Speter			if (!((j + 1) & 0xf)) {
132531183Speter				s -= 15;
132631183Speter				sprintf((char *)t, "	");
132731183Speter				t += 8;
132831183Speter				for (k = 16; k; k--, s++)
1329255332Scy					*t++ = (isprint(*s) ? *s : '.');
133031183Speter				s--;
133131183Speter			}
133231183Speter
133331183Speter			if ((j + 1) & 0xf)
133431183Speter				*t++ = ' ';;
133531183Speter		}
133631183Speter
133731183Speter		if (j & 0xf) {
133831183Speter			for (k = 16 - (j & 0xf); k; k--) {
133931183Speter				*t++ = ' ';
134031183Speter				*t++ = ' ';
134131183Speter				*t++ = ' ';
134231183Speter			}
134331183Speter			sprintf((char *)t, "       ");
134431183Speter			t += 7;
134531183Speter			s -= j & 0xf;
134631183Speter			for (k = j & 0xf; k; k--, s++)
1347255332Scy				*t++ = (isprint(*s) ? *s : '.');
134831183Speter			*t++ = '\n';
134931183Speter			*t = '\0';
135031183Speter		}
135131183Speter		fputs(outline, stdout);
135231183Speter		fflush(stdout);
135337074Speter		ip->ip_len = ntohs(ip->ip_len);
135431183Speter	}
135531183Speter
135631183Speter	prep_packet();
135731183Speter	free_aniplist();
135831183Speter}
135931183Speter
136031183Speter
136131183Spetervoid new_interface()
136231183Speter{
136331183Speter	cifp = (iface_t *)calloc(1, sizeof(iface_t));
136431183Speter	*iftail = cifp;
136531183Speter	iftail = &cifp->if_next;
136631183Speter	cifp->if_fd = -1;
136731183Speter}
136831183Speter
136931183Speter
137031183Spetervoid check_interface()
137131183Speter{
137231183Speter	if (!cifp->if_name || !*cifp->if_name)
137331183Speter		fprintf(stderr, "No interface name given!\n");
137431183Speter	if (!cifp->if_MTU || !*cifp->if_name)
137531183Speter		fprintf(stderr, "Interface %s has an MTU of 0!\n",
137631183Speter			cifp->if_name);
137731183Speter}
137831183Speter
137931183Speter
138031183Spetervoid set_ifname(arg)
138131183Speterchar **arg;
138231183Speter{
138331183Speter	cifp->if_name = *arg;
138431183Speter	*arg = NULL;
138531183Speter}
138631183Speter
138731183Speter
138831183Spetervoid set_ifmtu(arg)
138931183Speterint arg;
139031183Speter{
139131183Speter	cifp->if_MTU = arg;
139231183Speter}
139331183Speter
139431183Speter
139531183Spetervoid set_ifv4addr(arg)
139631183Speterchar **arg;
139731183Speter{
139831183Speter	cifp->if_addr = getipv4addr(*arg);
139931183Speter	free(*arg);
140031183Speter	*arg = NULL;
140131183Speter}
140231183Speter
140331183Speter
140431183Spetervoid set_ifeaddr(arg)
140531183Speterchar **arg;
140631183Speter{
140731183Speter	(void) geteaddr(*arg, &cifp->if_eaddr);
140831183Speter	free(*arg);
140931183Speter	*arg = NULL;
141031183Speter}
141131183Speter
141231183Speter
141331183Spetervoid new_arp()
141431183Speter{
141531183Speter	carp = (arp_t *)calloc(1, sizeof(arp_t));
141631183Speter	*arptail = carp;
141731183Speter	arptail = &carp->arp_next;
141831183Speter}
141931183Speter
142031183Speter
142131183Spetervoid set_arpeaddr(arg)
142231183Speterchar **arg;
142331183Speter{
142431183Speter	(void) geteaddr(*arg, &carp->arp_eaddr);
142531183Speter	free(*arg);
142631183Speter	*arg = NULL;
142731183Speter}
142831183Speter
142931183Speter
143031183Spetervoid set_arpv4addr(arg)
143131183Speterchar **arg;
143231183Speter{
143331183Speter	carp->arp_addr = getipv4addr(*arg);
143431183Speter	free(*arg);
143531183Speter	*arg = NULL;
143631183Speter}
143731183Speter
143831183Speter
143953024Sguidoint arp_getipv4(ip, addr)
144053024Sguidochar *ip;
144153024Sguidochar *addr;
144253024Sguido{
144353024Sguido	arp_t *a;
144453024Sguido
144553024Sguido	for (a = arplist; a; a = a->arp_next)
144653024Sguido		if (!bcmp(ip, (char *)&a->arp_addr, 4)) {
144753024Sguido			bcopy((char *)&a->arp_eaddr, addr, 6);
144853024Sguido			return 0;
144953024Sguido		}
145053024Sguido	return -1;
145153024Sguido}
145253024Sguido
145353024Sguido
145431183Spetervoid reset_send()
145531183Speter{
145631183Speter	sending.snd_if = iflist;
145731183Speter	sending.snd_gw = defrouter;
145831183Speter}
145931183Speter
146031183Speter
146131183Spetervoid set_sendif(arg)
146231183Speterchar **arg;
146331183Speter{
146431183Speter	iface_t	*ifp;
146531183Speter
146631183Speter	for (ifp = iflist; ifp; ifp = ifp->if_next)
146731183Speter		if (ifp->if_name && !strcmp(ifp->if_name, *arg))
146831183Speter			break;
146931183Speter	sending.snd_if = ifp;
147031183Speter	if (!ifp)
147131183Speter		fprintf(stderr, "couldn't find interface %s\n", *arg);
147231183Speter	free(*arg);
147331183Speter	*arg = NULL;
147431183Speter}
147531183Speter
147631183Speter
147731183Spetervoid set_sendvia(arg)
147831183Speterchar **arg;
147931183Speter{
148031183Speter	sending.snd_gw = getipv4addr(*arg);
148131183Speter	free(*arg);
148231183Speter	*arg = NULL;
148331183Speter}
148431183Speter
148531183Speter
148631183Spetervoid set_defaultrouter(arg)
148731183Speterchar **arg;
148831183Speter{
148931183Speter	defrouter = getipv4addr(*arg);
149031183Speter	free(*arg);
149131183Speter	*arg = NULL;
149231183Speter}
149331183Speter
149431183Speter
149531183Spetervoid new_icmpheader()
149631183Speter{
149731183Speter	if ((ip->ip_p) && (ip->ip_p != IPPROTO_ICMP)) {
149831183Speter		fprintf(stderr, "protocol %d specified with ICMP!\n",
149931183Speter			ip->ip_p);
150031183Speter		return;
150131183Speter	}
150231183Speter	ip->ip_p = IPPROTO_ICMP;
150331183Speter	icmp = (icmphdr_t *)new_header(IPPROTO_ICMP);
150431183Speter}
150531183Speter
150631183Speter
150731183Spetervoid set_icmpcode(code)
150831183Speterint code;
150931183Speter{
151031183Speter	icmp->icmp_code = code;
151131183Speter}
151231183Speter
151331183Speter
151431183Spetervoid set_icmptype(type)
151531183Speterint type;
151631183Speter{
151731183Speter	icmp->icmp_type = type;
151831183Speter}
151931183Speter
152031183Speter
152131183Spetervoid set_icmpcodetok(code)
152231183Speterchar **code;
152331183Speter{
152431183Speter	char	*s;
152531183Speter	int	i;
152631183Speter
152731183Speter	for (i = 0; (s = icmpcodes[i]); i++)
152831183Speter		if (!strcmp(s, *code)) {
152931183Speter			icmp->icmp_code = i;
153031183Speter			break;
153131183Speter		}
153231183Speter	if (!s)
153331183Speter		fprintf(stderr, "unknown ICMP code %s\n", *code);
153431183Speter	free(*code);
153531183Speter	*code = NULL;
153631183Speter}
153731183Speter
153831183Speter
153931183Spetervoid set_icmptypetok(type)
154031183Speterchar **type;
154131183Speter{
154231183Speter	char	*s;
154331183Speter	int	i, done = 0;
154431183Speter
154531183Speter	for (i = 0; !(s = icmptypes[i]) || strcmp(s, "END"); i++)
154631183Speter		if (s && !strcmp(s, *type)) {
154731183Speter			icmp->icmp_type = i;
154831183Speter			done = 1;
154931183Speter			break;
155031183Speter		}
155131183Speter	if (!done)
155231183Speter		fprintf(stderr, "unknown ICMP type %s\n", *type);
155331183Speter	free(*type);
155431183Speter	*type = NULL;
155531183Speter}
155631183Speter
155731183Speter
155831183Spetervoid set_icmpid(arg)
155931183Speterint arg;
156031183Speter{
156137074Speter	icmp->icmp_id = htons(arg);
156231183Speter}
156331183Speter
156431183Speter
156531183Spetervoid set_icmpseq(arg)
156631183Speterint arg;
156731183Speter{
156837074Speter	icmp->icmp_seq = htons(arg);
156931183Speter}
157031183Speter
157131183Speter
157231183Spetervoid set_icmpotime(arg)
157331183Speterint arg;
157431183Speter{
157537074Speter	icmp->icmp_otime = htonl(arg);
157631183Speter}
157731183Speter
157831183Speter
157931183Spetervoid set_icmprtime(arg)
158031183Speterint arg;
158131183Speter{
158237074Speter	icmp->icmp_rtime = htonl(arg);
158331183Speter}
158431183Speter
158531183Speter
158631183Spetervoid set_icmpttime(arg)
158731183Speterint arg;
158831183Speter{
158937074Speter	icmp->icmp_ttime = htonl(arg);
159031183Speter}
159131183Speter
159231183Speter
159331183Spetervoid set_icmpmtu(arg)
159431183Speterint arg;
159531183Speter{
159631183Speter#if	BSD >= 199306
159737074Speter	icmp->icmp_nextmtu = htons(arg);
159831183Speter#endif
159931183Speter}
160031183Speter
160131183Speter
160231183Spetervoid set_redir(redir, arg)
160331183Speterint redir;
160431183Speterchar **arg;
160531183Speter{
160631183Speter	icmp->icmp_code = redir;
160731183Speter	icmp->icmp_gwaddr = getipv4addr(*arg);
160831183Speter	free(*arg);
160931183Speter	*arg = NULL;
161031183Speter}
161131183Speter
161231183Speter
161331183Spetervoid set_icmppprob(num)
161431183Speterint num;
161531183Speter{
161631183Speter	icmp->icmp_pptr = num;
161731183Speter}
161831183Speter
161931183Speter
162031183Spetervoid new_ipv4opt()
162131183Speter{
162231183Speter	new_header(-2);
162331183Speter}
162431183Speter
162531183Speter
162631183Spetervoid add_ipopt(state, ptr)
162731183Speterint state;
162831183Spetervoid *ptr;
162931183Speter{
163031183Speter	struct ipopt_names *io;
163131183Speter	struct statetoopt *sto;
163231183Speter	char numbuf[16], *arg, **param = ptr;
163331183Speter	int inc, hlen;
163431183Speter
163531183Speter	if (state == IL_IPO_RR || state == IL_IPO_SATID) {
163631183Speter		if (param)
163731183Speter			sprintf(numbuf, "%d", *(int *)param);
163831183Speter		else
163931183Speter			strcpy(numbuf, "0");
164031183Speter		arg = numbuf;
164131183Speter	} else
164231183Speter		arg = param ? *param : NULL;
164331183Speter
164431183Speter	if (canip->ah_next) {
164531183Speter		fprintf(stderr, "cannot specify options after data body\n");
164631183Speter		return;
164731183Speter	}
164831183Speter	for (sto = toipopts; sto->sto_st; sto++)
164931183Speter		if (sto->sto_st == state)
165031183Speter			break;
1651161357Sguido	if (!sto->sto_st) {
165231183Speter		fprintf(stderr, "No mapping for state %d to IP option\n",
165331183Speter			state);
165431183Speter		return;
165531183Speter	}
165631183Speter
165731183Speter	hlen = sizeof(ip_t) + canip->ah_optlen;
165831183Speter	for (io = ionames; io->on_name; io++)
165931183Speter		if (io->on_value == sto->sto_op)
166031183Speter			break;
166131183Speter	canip->ah_lastopt = io->on_value;
166231183Speter
166331183Speter	if (io->on_name) {
166431183Speter		inc = addipopt((char *)ip + hlen, io, hlen - sizeof(ip_t),arg);
166531183Speter		if (inc > 0) {
166631183Speter			while (inc & 3) {
166731183Speter				((char *)ip)[sizeof(*ip) + inc] = IPOPT_NOP;
166831183Speter				canip->ah_lastopt = IPOPT_NOP;
166931183Speter				inc++;
167031183Speter			}
167131183Speter			hlen += inc;
167231183Speter		}
167331183Speter	}
167431183Speter
167531183Speter	canip->ah_optlen = hlen - sizeof(ip_t);
167631183Speter
167731183Speter	if (state != IL_IPO_RR && state != IL_IPO_SATID)
167831183Speter		if (param && *param) {
167931183Speter			free(*param);
168031183Speter			*param = NULL;
168131183Speter		}
168231183Speter	sclass = NULL;
168331183Speter}
168431183Speter
168531183Speter
168631183Spetervoid end_ipopt()
168731183Speter{
168831183Speter	int pad;
168931183Speter	char *s, *buf = (char *)ip;
169031183Speter
169131183Speter	/*
169231183Speter	 * pad out so that we have a multiple of 4 bytes in size fo the
169331183Speter	 * options.  make sure last byte is EOL.
169431183Speter	 */
169531183Speter	if (canip->ah_lastopt == IPOPT_NOP) {
169631183Speter		buf[sizeof(*ip) + canip->ah_optlen - 1] = IPOPT_EOL;
169731183Speter	} else if (canip->ah_lastopt != IPOPT_EOL) {
169831183Speter		s = buf + sizeof(*ip) + canip->ah_optlen;
169931183Speter
170031183Speter		for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) {
170131183Speter			*s++ = IPOPT_NOP;
170231183Speter			*s = IPOPT_EOL;
170331183Speter			canip->ah_optlen++;
170431183Speter		}
170531183Speter		canip->ah_optlen++;
170631183Speter	} else {
170731183Speter		s = buf + sizeof(*ip) + canip->ah_optlen - 1;
170831183Speter
170931183Speter		for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) {
171031183Speter			*s++ = IPOPT_NOP;
171131183Speter			*s = IPOPT_EOL;
171231183Speter			canip->ah_optlen++;
171331183Speter		}
171431183Speter	}
171531183Speter	ip->ip_hl = (sizeof(*ip) + canip->ah_optlen) >> 2;
171631183Speter	inc_anipheaders(canip->ah_optlen);
171731183Speter	free_anipheader();
171831183Speter}
171931183Speter
172031183Speter
172131183Spetervoid set_secclass(arg)
172231183Speterchar **arg;
172331183Speter{
172431183Speter	sclass = *arg;
172531183Speter	*arg = NULL;
172631183Speter}
172731183Speter
172831183Speter
172931183Spetervoid free_anipheader()
173031183Speter{
173131183Speter	aniphdr_t *aip;
173231183Speter
173331183Speter	aip = canip;
173431183Speter	if ((canip = aip->ah_prev)) {
173531183Speter		canip->ah_next = NULL;
173631183Speter		aniptail = &canip->ah_next;
173731183Speter	}
173834739Speter
173934739Speter	if (canip)
174034739Speter		free(aip);
174131183Speter}
174231183Speter
174331183Speter
174431183Spetervoid end_ipv4()
174531183Speter{
174631183Speter	aniphdr_t *aip;
174731183Speter
174831183Speter	ip->ip_sum = 0;
174937074Speter	ip->ip_len = htons(ip->ip_len);
175031183Speter	ip->ip_sum = chksum((u_short *)ip, ip->ip_hl << 2);
175137074Speter	ip->ip_len = ntohs(ip->ip_len);
175231183Speter	free_anipheader();
175331183Speter	for (aip = aniphead, ip = NULL; aip; aip = aip->ah_next)
175431183Speter		if (aip->ah_p == IPPROTO_IP)
175531183Speter			ip = aip->ah_ip;
175631183Speter}
175731183Speter
175831183Speter
175931183Spetervoid end_icmp()
176031183Speter{
176131183Speter	aniphdr_t *aip;
176231183Speter
176331183Speter	icmp->icmp_cksum = 0;
176431183Speter	icmp->icmp_cksum = chksum((u_short *)icmp, canip->ah_len);
176531183Speter	free_anipheader();
176631183Speter	for (aip = aniphead, icmp = NULL; aip; aip = aip->ah_next)
176731183Speter		if (aip->ah_p == IPPROTO_ICMP)
176831183Speter			icmp = aip->ah_icmp;
176931183Speter}
177031183Speter
177131183Speter
177231183Spetervoid end_udp()
177331183Speter{
177431183Speter	u_long	sum;
177531183Speter	aniphdr_t *aip;
177631183Speter	ip_t	iptmp;
177731183Speter
177831183Speter	bzero((char *)&iptmp, sizeof(iptmp));
177931183Speter	iptmp.ip_p = ip->ip_p;
178031183Speter	iptmp.ip_src = ip->ip_src;
178131183Speter	iptmp.ip_dst = ip->ip_dst;
178237074Speter	iptmp.ip_len = htons(ip->ip_len - (ip->ip_hl << 2));
178331183Speter	sum = p_chksum((u_short *)&iptmp, (u_int)sizeof(iptmp));
178437074Speter	udp->uh_ulen = htons(udp->uh_ulen);
178537074Speter	udp->uh_sum = c_chksum((u_short *)udp, (u_int)ntohs(iptmp.ip_len), sum);
178631183Speter	free_anipheader();
178731183Speter	for (aip = aniphead, udp = NULL; aip; aip = aip->ah_next)
178831183Speter		if (aip->ah_p == IPPROTO_UDP)
178931183Speter			udp = aip->ah_udp;
179031183Speter}
179131183Speter
179231183Speter
179331183Spetervoid end_tcp()
179431183Speter{
179531183Speter	u_long	sum;
179631183Speter	aniphdr_t *aip;
179731183Speter	ip_t	iptmp;
179831183Speter
179931183Speter	bzero((char *)&iptmp, sizeof(iptmp));
180031183Speter	iptmp.ip_p = ip->ip_p;
180131183Speter	iptmp.ip_src = ip->ip_src;
180231183Speter	iptmp.ip_dst = ip->ip_dst;
180337074Speter	iptmp.ip_len = htons(ip->ip_len - (ip->ip_hl << 2));
180431183Speter	sum = p_chksum((u_short *)&iptmp, (u_int)sizeof(iptmp));
180531183Speter	tcp->th_sum = 0;
180637074Speter	tcp->th_sum = c_chksum((u_short *)tcp, (u_int)ntohs(iptmp.ip_len), sum);
180731183Speter	free_anipheader();
180831183Speter	for (aip = aniphead, tcp = NULL; aip; aip = aip->ah_next)
180931183Speter		if (aip->ah_p == IPPROTO_TCP)
181031183Speter			tcp = aip->ah_tcp;
181131183Speter}
181231183Speter
181331183Speter
181431183Spetervoid end_data()
181531183Speter{
181631183Speter	free_anipheader();
181731183Speter}
181831183Speter
181931183Speter
182031183Spetervoid iplang(fp)
182131183SpeterFILE *fp;
182231183Speter{
182331183Speter	yyin = fp;
182431183Speter
182531183Speter	yydebug = (opts & OPT_DEBUG) ? 1 : 0;
182631183Speter
182731183Speter	while (!feof(fp))
182831183Speter		yyparse();
182931183Speter}
183031183Speter
183131183Speter
183231183Speteru_short	c_chksum(buf, len, init)
183331183Speteru_short	*buf;
183431183Speteru_int	len;
183531183Speteru_long	init;
183631183Speter{
183731183Speter	u_long	sum = init;
183831183Speter	int	nwords = len >> 1;
1839255332Scy
184031183Speter	for(; nwords > 0; nwords--)
184131183Speter		sum += *buf++;
184231183Speter	sum = (sum>>16) + (sum & 0xffff);
184331183Speter	sum += (sum >>16);
184431183Speter	return (~sum);
184531183Speter}
184631183Speter
184731183Speter
184831183Speteru_long	p_chksum(buf,len)
184931183Speteru_short	*buf;
185031183Speteru_int	len;
185131183Speter{
185231183Speter	u_long	sum = 0;
185331183Speter	int	nwords = len >> 1;
1854255332Scy
185531183Speter	for(; nwords > 0; nwords--)
185631183Speter		sum += *buf++;
185731183Speter	return sum;
185831183Speter}
1859