xref: /freebsd/sbin/ipf/iplang/iplang_y.y (revision 71625ec9ad2a9bc8c09784fbd23b759830e0ee5f)
1 /*	$FreeBSD$	*/
2 
3 %{
4 /*
5  * Copyright (C) 2012 by Darren Reed.
6  *
7  * See the IPFILTER.LICENCE file for details on licencing.
8  *
9  * Id: iplang_y.y,v 2.9.2.4 2006/03/17 12:11:29 darrenr Exp $
10  */
11 
12 #include <stdio.h>
13 #include <string.h>
14 #include <fcntl.h>
15 #if !defined(__SVR4) && !defined(__svr4__)
16 # include <strings.h>
17 #else
18 # include <sys/byteorder.h>
19 #endif
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/param.h>
23 #include <sys/time.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <stddef.h>
27 #include <sys/socket.h>
28 #include <net/if.h>
29 #include <netinet/in.h>
30 #include <netinet/in_systm.h>
31 #include <netinet/ip.h>
32 # include <netinet/ip_var.h>
33 # include <net/route.h>
34 # include <netinet/if_ether.h>
35 #include <netdb.h>
36 #include <arpa/nameser.h>
37 #include <arpa/inet.h>
38 #include <resolv.h>
39 #include <ctype.h>
40 #include "ipsend.h"
41 #include "ip_compat.h"
42 #include "ipf.h"
43 #include "iplang.h"
44 
45 extern	int	opts;
46 extern	struct ipopt_names ionames[];
47 extern	int	state, state, lineNum, token;
48 extern	int	yylineno;
49 extern	char	yytext[];
50 extern	FILE	*yyin;
51 int	yylex	__P((void));
52 #define	YYDEBUG 1
53 int	yydebug = 1;
54 
55 iface_t *iflist = NULL, **iftail = &iflist;
56 iface_t *cifp = NULL;
57 arp_t *arplist = NULL, **arptail = &arplist, *carp = NULL;
58 struct in_addr defrouter;
59 send_t	sending;
60 char	*sclass = NULL;
61 u_short	c_chksum(u_short *, u_int, u_long);
62 u_long	p_chksum(u_short *, u_int);
63 
64 u_long	ipbuffer[67584/sizeof(u_long)];		/* 66K */
65 aniphdr_t	*aniphead = NULL, *canip = NULL, **aniptail = &aniphead;
66 ip_t		*ip = NULL;
67 udphdr_t	*udp = NULL;
68 tcphdr_t	*tcp = NULL;
69 icmphdr_t	*icmp = NULL;
70 
71 struct statetoopt {
72 	int	sto_st;
73 	int	sto_op;
74 };
75 
76 struct	in_addr getipv4addr(char *arg);
77 u_short	getportnum(char *, char *);
78 struct	ether_addr *geteaddr(char *, struct ether_addr *);
79 void	*new_header(int);
80 void	free_aniplist(void);
81 void	inc_anipheaders(int);
82 void	new_data(void);
83 void	set_datalen(char **);
84 void	set_datafile(char **);
85 void	set_data(char **);
86 void	new_packet(void);
87 void	set_ipv4proto(char **);
88 void	set_ipv4src(char **);
89 void	set_ipv4dst(char **);
90 void	set_ipv4off(char **);
91 void	set_ipv4v(char **);
92 void	set_ipv4hl(char **);
93 void	set_ipv4ttl(char **);
94 void	set_ipv4tos(char **);
95 void	set_ipv4id(char **);
96 void	set_ipv4sum(char **);
97 void	set_ipv4len(char **);
98 void	new_tcpheader(void);
99 void	set_tcpsport(char **);
100 void	set_tcpdport(char **);
101 void	set_tcpseq(char **);
102 void	set_tcpack(char **);
103 void	set_tcpoff(char **);
104 void	set_tcpurp(char **);
105 void	set_tcpwin(char **);
106 void	set_tcpsum(char **);
107 void	set_tcpflags(char **);
108 void	set_tcpopt(int, char **);
109 void	end_tcpopt(void);
110 void	new_udpheader(void);
111 void	set_udplen(char **);
112 void	set_udpsum(char **);
113 void	prep_packet(void);
114 void	packet_done(void);
115 void	new_interface(void);
116 void	check_interface(void);
117 void	set_ifname(char **);
118 void	set_ifmtu(int);
119 void	set_ifv4addr(char **);
120 void	set_ifeaddr(char **);
121 void	new_arp(void);
122 void	set_arpeaddr(char **);
123 void	set_arpv4addr(char **);
124 void	reset_send(void);
125 void	set_sendif(char **);
126 void	set_sendvia(char **);
127 void	set_defaultrouter(char **);
128 void	new_icmpheader(void);
129 void	set_icmpcode(int);
130 void	set_icmptype(int);
131 void	set_icmpcodetok(char **);
132 void	set_icmptypetok(char **);
133 void	set_icmpid(int);
134 void	set_icmpseq(int);
135 void	set_icmpotime(int);
136 void	set_icmprtime(int);
137 void	set_icmpttime(int);
138 void	set_icmpmtu(int);
139 void	set_redir(int, char **);
140 void	new_ipv4opt(void);
141 void	set_icmppprob(int);
142 void	add_ipopt(int, void *);
143 void	end_ipopt(void);
144 void	set_secclass(char **);
145 void	free_anipheader(void);
146 void	end_ipv4(void);
147 void	end_icmp(void);
148 void	end_udp(void);
149 void	end_tcp(void);
150 void	end_data(void);
151 void	yyerror(char *);
152 void	iplang(FILE *);
153 int	arp_getipv4(char *, char *);
154 int	yyparse(void);
155 %}
156 %union {
157 	char	*str;
158 	int	num;
159 }
160 %token	<num> IL_NUMBER
161 %type	<num> number digits optnumber
162 %token	<str> IL_TOKEN
163 %type	<str> token optoken
164 %token	IL_HEXDIGIT IL_COLON IL_DOT IL_EOF IL_COMMENT
165 %token	IL_INTERFACE IL_IFNAME IL_MTU IL_EADDR
166 %token	IL_IPV4 IL_V4PROTO IL_V4SRC IL_V4DST IL_V4OFF IL_V4V IL_V4HL IL_V4TTL
167 %token	IL_V4TOS IL_V4SUM IL_V4LEN IL_V4OPT IL_V4ID
168 %token	IL_TCP IL_SPORT IL_DPORT IL_TCPFL IL_TCPSEQ IL_TCPACK IL_TCPOFF
169 %token	IL_TCPWIN IL_TCPSUM IL_TCPURP IL_TCPOPT IL_TCPO_NOP IL_TCPO_EOL
170 %token	IL_TCPO_MSS IL_TCPO_WSCALE IL_TCPO_TS
171 %token	IL_UDP IL_UDPLEN IL_UDPSUM
172 %token	IL_ICMP IL_ICMPTYPE IL_ICMPCODE
173 %token	IL_SEND IL_VIA
174 %token	IL_ARP
175 %token	IL_DEFROUTER
176 %token	IL_SUM IL_OFF IL_LEN IL_V4ADDR IL_OPT
177 %token	IL_DATA IL_DLEN IL_DVALUE IL_DFILE
178 %token	IL_IPO_NOP IL_IPO_RR IL_IPO_ZSU IL_IPO_MTUP IL_IPO_MTUR IL_IPO_EOL
179 %token	IL_IPO_TS IL_IPO_TR IL_IPO_SEC IL_IPO_LSRR IL_IPO_ESEC
180 %token	IL_IPO_SATID IL_IPO_SSRR IL_IPO_ADDEXT IL_IPO_VISA IL_IPO_IMITD
181 %token	IL_IPO_EIP IL_IPO_FINN IL_IPO_SECCLASS IL_IPO_CIPSO IL_IPO_ENCODE
182 %token	<str> IL_IPS_RESERV4 IL_IPS_TOPSECRET IL_IPS_SECRET IL_IPS_RESERV3
183 %token	<str> IL_IPS_CONFID IL_IPS_UNCLASS IL_IPS_RESERV2 IL_IPS_RESERV1
184 %token	IL_ICMP_ECHOREPLY IL_ICMP_UNREACH IL_ICMP_UNREACH_NET
185 %token	IL_ICMP_UNREACH_HOST IL_ICMP_UNREACH_PROTOCOL IL_ICMP_UNREACH_PORT
186 %token	IL_ICMP_UNREACH_NEEDFRAG IL_ICMP_UNREACH_SRCFAIL
187 %token	IL_ICMP_UNREACH_NET_UNKNOWN IL_ICMP_UNREACH_HOST_UNKNOWN
188 %token	IL_ICMP_UNREACH_ISOLATED IL_ICMP_UNREACH_NET_PROHIB
189 %token	IL_ICMP_UNREACH_HOST_PROHIB IL_ICMP_UNREACH_TOSNET
190 %token	IL_ICMP_UNREACH_TOSHOST IL_ICMP_UNREACH_FILTER_PROHIB
191 %token	IL_ICMP_UNREACH_HOST_PRECEDENCE IL_ICMP_UNREACH_PRECEDENCE_CUTOFF
192 %token	IL_ICMP_SOURCEQUENCH IL_ICMP_REDIRECT IL_ICMP_REDIRECT_NET
193 %token	IL_ICMP_REDIRECT_HOST IL_ICMP_REDIRECT_TOSNET
194 %token	IL_ICMP_REDIRECT_TOSHOST IL_ICMP_ECHO IL_ICMP_ROUTERADVERT
195 %token	IL_ICMP_ROUTERSOLICIT IL_ICMP_TIMXCEED IL_ICMP_TIMXCEED_INTRANS
196 %token	IL_ICMP_TIMXCEED_REASS IL_ICMP_PARAMPROB IL_ICMP_PARAMPROB_OPTABSENT
197 %token	IL_ICMP_TSTAMP IL_ICMP_TSTAMPREPLY IL_ICMP_IREQ IL_ICMP_IREQREPLY
198 %token	IL_ICMP_MASKREQ IL_ICMP_MASKREPLY IL_ICMP_SEQ IL_ICMP_ID
199 %token	IL_ICMP_OTIME IL_ICMP_RTIME IL_ICMP_TTIME
200 
201 %%
202 file:	line
203 	| line file
204 	| IL_COMMENT
205 	| IL_COMMENT file
206 	;
207 
208 line:	iface
209 	| arp
210 	| send
211 	| defrouter
212 	| ipline
213 	;
214 
215 iface:  ifhdr '{' ifaceopts '}' ';'	{ check_interface(); }
216 	;
217 
218 ifhdr:	IL_INTERFACE			{ new_interface(); }
219 	;
220 
221 ifaceopts:
222 	ifaceopt
223 	| ifaceopt ifaceopts
224 	;
225 
226 ifaceopt:
227 	IL_IFNAME token			{ set_ifname(&$2); }
228 	| IL_MTU number			{ set_ifmtu($2); }
229 	| IL_V4ADDR token		{ set_ifv4addr(&$2); }
230 	| IL_EADDR token		{ set_ifeaddr(&$2); }
231 	;
232 
233 send:   sendhdr '{' sendbody '}' ';'	{ packet_done(); }
234 	| sendhdr ';'			{ packet_done(); }
235 	;
236 
237 sendhdr:
238 	IL_SEND				{ reset_send(); }
239 	;
240 
241 sendbody:
242 	sendopt
243 	| sendbody sendopt
244 	;
245 
246 sendopt:
247 	IL_IFNAME token			{ set_sendif(&$2); }
248 	| IL_VIA token			{ set_sendvia(&$2); }
249 	;
250 
251 arp:    arphdr '{' arpbody '}' ';'
252 	;
253 
254 arphdr:	IL_ARP				{ new_arp(); }
255 	;
256 
257 arpbody:
258 	arpopt
259 	| arpbody arpopt
260 	;
261 
262 arpopt: IL_V4ADDR token			{ set_arpv4addr(&$2); }
263 	| IL_EADDR token		{ set_arpeaddr(&$2); }
264 	;
265 
266 defrouter:
267 	IL_DEFROUTER token		{ set_defaultrouter(&$2); }
268 	;
269 
270 bodyline:
271 	ipline
272 	| tcp tcpline
273 	| udp udpline
274 	| icmp icmpline
275 	| data dataline
276 	;
277 
278 ipline:	ipv4 '{' ipv4body '}' ';'	{ end_ipv4(); }
279 	;
280 
281 ipv4:	IL_IPV4				{ new_packet(); }
282 
283 ipv4body:
284 	ipv4type
285 	| ipv4type ipv4body
286 	| bodyline
287 	;
288 
289 ipv4type:
290 	IL_V4PROTO token		{ set_ipv4proto(&$2); }
291 	| IL_V4SRC token		{ set_ipv4src(&$2); }
292 	| IL_V4DST token		{ set_ipv4dst(&$2); }
293 	| IL_V4OFF token		{ set_ipv4off(&$2); }
294 	| IL_V4V token			{ set_ipv4v(&$2); }
295 	| IL_V4HL token			{ set_ipv4hl(&$2); }
296 	| IL_V4ID token			{ set_ipv4id(&$2); }
297 	| IL_V4TTL token		{ set_ipv4ttl(&$2); }
298 	| IL_V4TOS token		{ set_ipv4tos(&$2); }
299 	| IL_V4SUM token		{ set_ipv4sum(&$2); }
300 	| IL_V4LEN token		{ set_ipv4len(&$2); }
301 	| ipv4opt '{' ipv4optlist '}' ';'	{ end_ipopt(); }
302 	;
303 
304 tcp:	IL_TCP				{ new_tcpheader(); }
305 	;
306 
307 tcpline:
308 	'{' tcpheader '}' ';'		{ end_tcp(); }
309 	;
310 
311 tcpheader:
312 	tcpbody
313 	| tcpbody tcpheader
314 	| bodyline
315 	;
316 
317 tcpbody:
318 	IL_SPORT token			{ set_tcpsport(&$2); }
319 	| IL_DPORT token		{ set_tcpdport(&$2); }
320 	| IL_TCPSEQ token		{ set_tcpseq(&$2); }
321 	| IL_TCPACK token		{ set_tcpack(&$2); }
322 	| IL_TCPOFF token		{ set_tcpoff(&$2); }
323 	| IL_TCPURP token		{ set_tcpurp(&$2); }
324 	| IL_TCPWIN token		{ set_tcpwin(&$2); }
325 	| IL_TCPSUM token		{ set_tcpsum(&$2); }
326 	| IL_TCPFL token		{ set_tcpflags(&$2); }
327 	| IL_TCPOPT '{' tcpopts '}' ';'	{ end_tcpopt(); }
328 	;
329 
330 tcpopts:
331 	| tcpopt tcpopts
332 	;
333 
334 tcpopt:	IL_TCPO_NOP ';'			{ set_tcpopt(IL_TCPO_NOP, NULL); }
335 	| IL_TCPO_EOL ';'		{ set_tcpopt(IL_TCPO_EOL, NULL); }
336 	| IL_TCPO_MSS optoken		{ set_tcpopt(IL_TCPO_MSS,&$2);}
337 	| IL_TCPO_WSCALE optoken	{ set_tcpopt(IL_TCPO_WSCALE,&$2);}
338 	| IL_TCPO_TS optoken		{ set_tcpopt(IL_TCPO_TS, &$2);}
339 	;
340 
341 udp:	IL_UDP				{ new_udpheader(); }
342 	;
343 
344 udpline:
345 	'{' udpheader '}' ';'		{ end_udp(); }
346 	;
347 
348 
349 udpheader:
350 	udpbody
351 	| udpbody udpheader
352 	| bodyline
353 	;
354 
355 udpbody:
356 	IL_SPORT token			{ set_tcpsport(&$2); }
357 	| IL_DPORT token		{ set_tcpdport(&$2); }
358 	| IL_UDPLEN token		{ set_udplen(&$2); }
359 	| IL_UDPSUM token		{ set_udpsum(&$2); }
360 	;
361 
362 icmp:	IL_ICMP				{ new_icmpheader(); }
363 	;
364 
365 icmpline:
366 	'{' icmpbody '}' ';'		{ end_icmp(); }
367 	;
368 
369 icmpbody:
370 	icmpheader
371 	| icmpheader bodyline
372 	;
373 
374 icmpheader:
375 	IL_ICMPTYPE icmptype
376 	| IL_ICMPTYPE icmptype icmpcode
377 	;
378 
379 icmpcode:
380 	IL_ICMPCODE token		{ set_icmpcodetok(&$2); }
381 	;
382 
383 icmptype:
384 	IL_ICMP_ECHOREPLY ';'		{ set_icmptype(ICMP_ECHOREPLY); }
385 	| IL_ICMP_ECHOREPLY '{' icmpechoopts '}' ';'
386 	| unreach
387 	| IL_ICMP_SOURCEQUENCH ';'	{ set_icmptype(ICMP_SOURCEQUENCH); }
388 	| redirect
389 	| IL_ICMP_ROUTERADVERT ';'	{ set_icmptype(ICMP_ROUTERADVERT); }
390 	| IL_ICMP_ROUTERSOLICIT ';'	{ set_icmptype(ICMP_ROUTERSOLICIT); }
391 	| IL_ICMP_ECHO ';'		{ set_icmptype(ICMP_ECHO); }
392 	| IL_ICMP_ECHO '{' icmpechoopts '}' ';'
393 	| IL_ICMP_TIMXCEED ';'		{ set_icmptype(ICMP_TIMXCEED); }
394 	| IL_ICMP_TIMXCEED '{' exceed '}' ';'
395 	| IL_ICMP_TSTAMP ';'		{ set_icmptype(ICMP_TSTAMP); }
396 	| IL_ICMP_TSTAMPREPLY ';'	{ set_icmptype(ICMP_TSTAMPREPLY); }
397 	| IL_ICMP_TSTAMPREPLY '{' icmptsopts '}' ';'
398 	| IL_ICMP_IREQ ';'		{ set_icmptype(ICMP_IREQ); }
399 	| IL_ICMP_IREQREPLY ';'		{ set_icmptype(ICMP_IREQREPLY); }
400 	| IL_ICMP_IREQREPLY '{' data dataline '}' ';'
401 	| IL_ICMP_MASKREQ ';'		{ set_icmptype(ICMP_MASKREQ); }
402 	| IL_ICMP_MASKREPLY ';'		{ set_icmptype(ICMP_MASKREPLY); }
403 	| IL_ICMP_MASKREPLY '{' token '}' ';'
404 	| IL_ICMP_PARAMPROB ';'		{ set_icmptype(ICMP_PARAMPROB); }
405 	| IL_ICMP_PARAMPROB '{' paramprob '}' ';'
406 	| IL_TOKEN ';'			{ set_icmptypetok(&$1); }
407 	;
408 
409 icmpechoopts:
410 	| icmpechoopts icmpecho
411 	;
412 
413 icmpecho:
414 	IL_ICMP_SEQ number 		{ set_icmpseq($2); }
415 	| IL_ICMP_ID number		{ set_icmpid($2); }
416 	;
417 
418 icmptsopts:
419 	| icmptsopts icmpts ';'
420 	;
421 
422 icmpts: IL_ICMP_OTIME number 		{ set_icmpotime($2); }
423 	| IL_ICMP_RTIME number 		{ set_icmprtime($2); }
424 	| IL_ICMP_TTIME number 		{ set_icmpttime($2); }
425 	;
426 
427 unreach:
428 	IL_ICMP_UNREACH
429 	| IL_ICMP_UNREACH '{' unreachopts '}' ';'
430 	;
431 
432 unreachopts:
433 	IL_ICMP_UNREACH_NET line
434 	| IL_ICMP_UNREACH_HOST line
435 	| IL_ICMP_UNREACH_PROTOCOL line
436 	| IL_ICMP_UNREACH_PORT line
437 	| IL_ICMP_UNREACH_NEEDFRAG number ';'	{ set_icmpmtu($2); }
438 	| IL_ICMP_UNREACH_SRCFAIL line
439 	| IL_ICMP_UNREACH_NET_UNKNOWN line
440 	| IL_ICMP_UNREACH_HOST_UNKNOWN line
441 	| IL_ICMP_UNREACH_ISOLATED line
442 	| IL_ICMP_UNREACH_NET_PROHIB line
443 	| IL_ICMP_UNREACH_HOST_PROHIB line
444 	| IL_ICMP_UNREACH_TOSNET line
445 	| IL_ICMP_UNREACH_TOSHOST line
446 	| IL_ICMP_UNREACH_FILTER_PROHIB line
447 	| IL_ICMP_UNREACH_HOST_PRECEDENCE line
448 	| IL_ICMP_UNREACH_PRECEDENCE_CUTOFF line
449 	;
450 
451 redirect:
452 	IL_ICMP_REDIRECT
453 	| IL_ICMP_REDIRECT '{' redirectopts '}' ';'
454 	;
455 
456 redirectopts:
457 	| IL_ICMP_REDIRECT_NET token		{ set_redir(0, &$2); }
458 	| IL_ICMP_REDIRECT_HOST token		{ set_redir(1, &$2); }
459 	| IL_ICMP_REDIRECT_TOSNET token		{ set_redir(2, &$2); }
460 	| IL_ICMP_REDIRECT_TOSHOST token	{ set_redir(3, &$2); }
461 	;
462 
463 exceed:
464 	IL_ICMP_TIMXCEED_INTRANS line
465 	| IL_ICMP_TIMXCEED_REASS line
466 	;
467 
468 paramprob:
469 	IL_ICMP_PARAMPROB_OPTABSENT
470 	| IL_ICMP_PARAMPROB_OPTABSENT paraprobarg
471 
472 paraprobarg:
473 	'{' number '}' ';'		{ set_icmppprob($2); }
474 	;
475 
476 ipv4opt:	IL_V4OPT		{ new_ipv4opt(); }
477 	;
478 
479 ipv4optlist:
480 	| ipv4opts ipv4optlist
481 	;
482 
483 ipv4opts:
484 	IL_IPO_NOP ';'			{ add_ipopt(IL_IPO_NOP, NULL); }
485 	| IL_IPO_RR optnumber		{ add_ipopt(IL_IPO_RR, &$2); }
486 	| IL_IPO_ZSU ';'		{ add_ipopt(IL_IPO_ZSU, NULL); }
487 	| IL_IPO_MTUP ';'		{ add_ipopt(IL_IPO_MTUP, NULL); }
488 	| IL_IPO_MTUR ';'		{ add_ipopt(IL_IPO_MTUR, NULL); }
489 	| IL_IPO_ENCODE ';'		{ add_ipopt(IL_IPO_ENCODE, NULL); }
490 	| IL_IPO_TS ';'			{ add_ipopt(IL_IPO_TS, NULL); }
491 	| IL_IPO_TR ';'			{ add_ipopt(IL_IPO_TR, NULL); }
492 	| IL_IPO_SEC ';'		{ add_ipopt(IL_IPO_SEC, NULL); }
493 	| IL_IPO_SECCLASS secclass	{ add_ipopt(IL_IPO_SECCLASS, sclass); }
494 	| IL_IPO_LSRR token		{ add_ipopt(IL_IPO_LSRR,&$2); }
495 	| IL_IPO_ESEC ';'		{ add_ipopt(IL_IPO_ESEC, NULL); }
496 	| IL_IPO_CIPSO ';'		{ add_ipopt(IL_IPO_CIPSO, NULL); }
497 	| IL_IPO_SATID optnumber	{ add_ipopt(IL_IPO_SATID,&$2);}
498 	| IL_IPO_SSRR token		{ add_ipopt(IL_IPO_SSRR,&$2); }
499 	| IL_IPO_ADDEXT ';'		{ add_ipopt(IL_IPO_ADDEXT, NULL); }
500 	| IL_IPO_VISA ';'		{ add_ipopt(IL_IPO_VISA, NULL); }
501 	| IL_IPO_IMITD ';'		{ add_ipopt(IL_IPO_IMITD, NULL); }
502 	| IL_IPO_EIP ';'		{ add_ipopt(IL_IPO_EIP, NULL); }
503 	| IL_IPO_FINN ';'		{ add_ipopt(IL_IPO_FINN, NULL); }
504 	;
505 
506 secclass:
507 	IL_IPS_RESERV4 ';'		{ set_secclass(&$1); }
508 	| IL_IPS_TOPSECRET ';'		{ set_secclass(&$1); }
509 	| IL_IPS_SECRET ';'		{ set_secclass(&$1); }
510 	| IL_IPS_RESERV3 ';'		{ set_secclass(&$1); }
511 	| IL_IPS_CONFID ';'		{ set_secclass(&$1); }
512 	| IL_IPS_UNCLASS ';'		{ set_secclass(&$1); }
513 	| IL_IPS_RESERV2 ';'		{ set_secclass(&$1); }
514 	| IL_IPS_RESERV1 ';'		{ set_secclass(&$1); }
515 	;
516 
517 data:	IL_DATA				{ new_data(); }
518 	;
519 
520 dataline:
521 	'{' databody '}' ';'		{ end_data(); }
522 	;
523 
524 databody: dataopts
525 	| dataopts databody
526 	;
527 
528 dataopts:
529 	IL_DLEN token			{ set_datalen(&$2); }
530 	| IL_DVALUE token 		{ set_data(&$2); }
531 	| IL_DFILE token 		{ set_datafile(&$2); }
532 	;
533 
534 token: IL_TOKEN ';'
535 	;
536 
537 optoken: ';'				{ $$ = ""; }
538 	| token
539 	;
540 
541 number: digits ';'
542 	;
543 
544 optnumber: ';'				{ $$ = 0; }
545 	| number
546 	;
547 
548 digits:	IL_NUMBER
549 	| digits IL_NUMBER
550 	;
551 %%
552 
553 struct	statetoopt	toipopts[] = {
554 	{ IL_IPO_NOP,		IPOPT_NOP },
555 	{ IL_IPO_RR,		IPOPT_RR },
556 	{ IL_IPO_ZSU,		IPOPT_ZSU },
557 	{ IL_IPO_MTUP,		IPOPT_MTUP },
558 	{ IL_IPO_MTUR,		IPOPT_MTUR },
559 	{ IL_IPO_ENCODE,	IPOPT_ENCODE },
560 	{ IL_IPO_TS,		IPOPT_TS },
561 	{ IL_IPO_TR,		IPOPT_TR },
562 	{ IL_IPO_SEC,		IPOPT_SECURITY },
563 	{ IL_IPO_SECCLASS,	IPOPT_SECURITY },
564 	{ IL_IPO_LSRR,		IPOPT_LSRR },
565 	{ IL_IPO_ESEC,		IPOPT_E_SEC },
566 	{ IL_IPO_CIPSO,		IPOPT_CIPSO },
567 	{ IL_IPO_SATID,		IPOPT_SATID },
568 	{ IL_IPO_SSRR,		IPOPT_SSRR },
569 	{ IL_IPO_ADDEXT,	IPOPT_ADDEXT },
570 	{ IL_IPO_VISA,		IPOPT_VISA },
571 	{ IL_IPO_IMITD,		IPOPT_IMITD },
572 	{ IL_IPO_EIP,		IPOPT_EIP },
573 	{ IL_IPO_FINN,		IPOPT_FINN },
574 	{ 0, 0 }
575 };
576 
577 struct	statetoopt	tosecopts[] = {
578 	{ IL_IPS_RESERV4,	IPSO_CLASS_RES4 },
579 	{ IL_IPS_TOPSECRET,	IPSO_CLASS_TOPS },
580 	{ IL_IPS_SECRET,	IPSO_CLASS_SECR },
581 	{ IL_IPS_RESERV3,	IPSO_CLASS_RES3 },
582 	{ IL_IPS_CONFID,	IPSO_CLASS_CONF },
583 	{ IL_IPS_UNCLASS,	IPSO_CLASS_UNCL },
584 	{ IL_IPS_RESERV2,	IPSO_CLASS_RES2 },
585 	{ IL_IPS_RESERV1,	IPSO_CLASS_RES1 },
586 	{ 0, 0 }
587 };
588 
589 
590 struct in_addr getipv4addr(arg)
591 char *arg;
592 {
593 	struct hostent *hp;
594 	struct in_addr in;
595 
596 	in.s_addr = 0xffffffff;
597 
598 	if ((hp = gethostbyname(arg)))
599 		bcopy(hp->h_addr, &in.s_addr, sizeof(struct in_addr));
600 	else
601 		in.s_addr = inet_addr(arg);
602 	return(in);
603 }
604 
605 
606 u_short getportnum(pr, name)
607 char *pr, *name;
608 {
609 	struct servent *sp;
610 
611 	if (!(sp = getservbyname(name, pr)))
612 		return(htons(atoi(name)));
613 	return(sp->s_port);
614 }
615 
616 
617 struct ether_addr *geteaddr(char *arg, struct ether_addr *buf)
618 {
619 	struct ether_addr *e;
620 
621 	e = ether_aton(arg);
622 	if (!e)
623 		fprintf(stderr, "Invalid ethernet address: %s\n", arg);
624 	else
625 # ifdef	__FreeBSD__
626 		bcopy(e->octet, buf->octet, sizeof(e->octet));
627 # else
628 		bcopy(e->ether_addr_octet, buf->ether_addr_octet,
629 		      sizeof(e->ether_addr_octet));
630 # endif
631 	return(e);
632 }
633 
634 
635 void *new_header(int type)
636 {
637 	aniphdr_t *aip, *oip = canip;
638 	int	sz = 0;
639 
640 	aip = (aniphdr_t *)calloc(1, sizeof(*aip));
641 	*aniptail = aip;
642 	aniptail = &aip->ah_next;
643 	aip->ah_p = type;
644 	aip->ah_prev = oip;
645 	canip = aip;
646 
647 	if (type == IPPROTO_UDP)
648 		sz = sizeof(udphdr_t);
649 	else if (type == IPPROTO_TCP)
650 		sz = sizeof(tcphdr_t);
651 	else if (type == IPPROTO_ICMP)
652 		sz = sizeof(icmphdr_t);
653 	else if (type == IPPROTO_IP)
654 		sz = sizeof(ip_t);
655 
656 	if (oip)
657 		canip->ah_data = oip->ah_data + oip->ah_len;
658 	else
659 		canip->ah_data = (char *)ipbuffer;
660 
661 	/*
662 	 * Increase the size fields in all wrapping headers.
663 	 */
664 	for (aip = aniphead; aip; aip = aip->ah_next) {
665 		aip->ah_len += sz;
666 		if (aip->ah_p == IPPROTO_IP)
667 			aip->ah_ip->ip_len += sz;
668 		else if (aip->ah_p == IPPROTO_UDP)
669 			aip->ah_udp->uh_ulen += sz;
670 	}
671 	return(void *)canip->ah_data;
672 }
673 
674 
675 void free_aniplist(void)
676 {
677 	aniphdr_t *aip, **aipp = &aniphead;
678 
679 	while ((aip = *aipp)) {
680 		*aipp = aip->ah_next;
681 		free(aip);
682 	}
683 	aniptail = &aniphead;
684 }
685 
686 
687 void inc_anipheaders(int inc)
688 {
689 	aniphdr_t *aip;
690 
691 	for (aip = aniphead; aip; aip = aip->ah_next) {
692 		aip->ah_len += inc;
693 		if (aip->ah_p == IPPROTO_IP)
694 			aip->ah_ip->ip_len += inc;
695 		else if (aip->ah_p == IPPROTO_UDP)
696 			aip->ah_udp->uh_ulen += inc;
697 	}
698 }
699 
700 
701 void new_data(void)
702 {
703 	(void) new_header(-1);
704 	canip->ah_len = 0;
705 }
706 
707 
708 void set_datalen(char **arg)
709 {
710 	int	len;
711 
712 	len = strtol(*arg, NULL, 0);
713 	inc_anipheaders(len);
714 	free(*arg);
715 	*arg = NULL;
716 }
717 
718 
719 void set_data(char **arg)
720 {
721 	u_char *s = (u_char *)*arg, *t = (u_char *)canip->ah_data, c;
722 	int len = 0, todo = 0, quote = 0, val = 0;
723 
724 	while ((c = *s++)) {
725 		if (todo) {
726 			if (ISDIGIT(c)) {
727 				todo--;
728 				if (c > '7') {
729 					fprintf(stderr, "octal with %c!\n", c);
730 					break;
731 				}
732 				val <<= 3;
733 				val |= (c - '0');
734 			}
735 			if (!ISDIGIT(c) || !todo) {
736 				*t++ = (u_char)(val & 0xff);
737 				todo = 0;
738 			}
739 			if (todo)
740 				continue;
741 		}
742 		if (quote) {
743 			if (ISDIGIT(c)) {
744 				todo = 2;
745 				if (c > '7') {
746 					fprintf(stderr, "octal with %c!\n", c);
747 					break;
748 				}
749 				val = (c - '0');
750 			} else {
751 				switch (c)
752 				{
753 				case '\"' :
754 					*t++ = '\"';
755 					break;
756 				case '\\' :
757 					*t++ = '\\';
758 					break;
759 				case 'n' :
760 					*t++ = '\n';
761 					break;
762 				case 'r' :
763 					*t++ = '\r';
764 					break;
765 				case 't' :
766 					*t++ = '\t';
767 					break;
768 				}
769 			}
770 			quote = 0;
771 			continue;
772 		}
773 
774 		if (c == '\\')
775 			quote = 1;
776 		else
777 			*t++ = c;
778 	}
779 	if (todo)
780 		*t++ = (u_char)(val & 0xff);
781 	if (quote)
782 		*t++ = '\\';
783 	len = t - (u_char *)canip->ah_data;
784 	inc_anipheaders(len - canip->ah_len);
785 	canip->ah_len = len;
786 }
787 
788 
789 void set_datafile(char **arg)
790 {
791 	struct stat sb;
792 	char *file = *arg;
793 	int fd, len;
794 
795 	if ((fd = open(file, O_RDONLY)) == -1) {
796 		perror("open");
797 		exit(-1);
798 	}
799 
800 	if (fstat(fd, &sb) == -1) {
801 		perror("fstat");
802 		exit(-1);
803 	}
804 
805 	if ((sb.st_size + aniphead->ah_len ) > 65535) {
806 		fprintf(stderr, "data file %s too big to include.\n", file);
807 		close(fd);
808 		return;
809 	}
810 	if ((len = read(fd, canip->ah_data, sb.st_size)) == -1) {
811 		perror("read");
812 		close(fd);
813 		return;
814 	}
815 	inc_anipheaders(len);
816 	canip->ah_len += len;
817 	close(fd);
818 }
819 
820 
821 void new_packet(void)
822 {
823 	static	u_short	id = 0;
824 
825 	if (!aniphead)
826 		bzero((char *)ipbuffer, sizeof(ipbuffer));
827 
828 	ip = (ip_t *)new_header(IPPROTO_IP);
829 	ip->ip_v = IPVERSION;
830 	ip->ip_hl = sizeof(ip_t) >> 2;
831 	ip->ip_len = sizeof(ip_t);
832 	ip->ip_ttl = 63;
833 	ip->ip_id = htons(id++);
834 }
835 
836 
837 void set_ipv4proto(arg)
838 char **arg;
839 {
840 	struct protoent *pr;
841 
842 	if ((pr = getprotobyname(*arg)))
843 		ip->ip_p = pr->p_proto;
844 	else
845 		if (!(ip->ip_p = atoi(*arg)))
846 			fprintf(stderr, "unknown protocol %s\n", *arg);
847 	free(*arg);
848 	*arg = NULL;
849 }
850 
851 
852 void set_ipv4src(char **arg)
853 {
854 	ip->ip_src = getipv4addr(*arg);
855 	free(*arg);
856 	*arg = NULL;
857 }
858 
859 
860 void set_ipv4dst(char **arg)
861 {
862 	ip->ip_dst = getipv4addr(*arg);
863 	free(*arg);
864 	*arg = NULL;
865 }
866 
867 
868 void set_ipv4off(char **arg)
869 {
870 	ip->ip_off = htons(strtol(*arg, NULL, 0));
871 	free(*arg);
872 	*arg = NULL;
873 }
874 
875 
876 void set_ipv4v(char **arg)
877 {
878 	ip->ip_v = strtol(*arg, NULL, 0);
879 	free(*arg);
880 	*arg = NULL;
881 }
882 
883 
884 void set_ipv4hl(char **arg)
885 {
886 	int newhl, inc;
887 
888 	newhl = strtol(*arg, NULL, 0);
889 	inc = (newhl - ip->ip_hl) << 2;
890 	ip->ip_len += inc;
891 	ip->ip_hl = newhl;
892 	canip->ah_len += inc;
893 	free(*arg);
894 	*arg = NULL;
895 }
896 
897 
898 void set_ipv4ttl(char **arg)
899 {
900 	ip->ip_ttl = strtol(*arg, NULL, 0);
901 	free(*arg);
902 	*arg = NULL;
903 }
904 
905 
906 void set_ipv4tos(char **arg)
907 {
908 	ip->ip_tos = strtol(*arg, NULL, 0);
909 	free(*arg);
910 	*arg = NULL;
911 }
912 
913 
914 void set_ipv4id(char **arg)
915 {
916 	ip->ip_id = htons(strtol(*arg, NULL, 0));
917 	free(*arg);
918 	*arg = NULL;
919 }
920 
921 
922 void set_ipv4sum(char **arg)
923 {
924 	ip->ip_sum = strtol(*arg, NULL, 0);
925 	free(*arg);
926 	*arg = NULL;
927 }
928 
929 
930 void set_ipv4len(char **arg)
931 {
932 	int len;
933 
934 	len = strtol(*arg, NULL, 0);
935 	inc_anipheaders(len - ip->ip_len);
936 	ip->ip_len = len;
937 	free(*arg);
938 	*arg = NULL;
939 }
940 
941 
942 void new_tcpheader(void)
943 {
944 
945 	if ((ip->ip_p) && (ip->ip_p != IPPROTO_TCP)) {
946 		fprintf(stderr, "protocol %d specified with TCP!\n", ip->ip_p);
947 		return;
948 	}
949 	ip->ip_p = IPPROTO_TCP;
950 
951 	tcp = (tcphdr_t *)new_header(IPPROTO_TCP);
952 	tcp->th_win = htons(4096);
953 	tcp->th_off = sizeof(*tcp) >> 2;
954 }
955 
956 
957 void set_tcpsport(char **arg)
958 {
959 	u_short *port;
960 	char *pr;
961 
962 	if (ip->ip_p == IPPROTO_UDP) {
963 		port = &udp->uh_sport;
964 		pr = "udp";
965 	} else {
966 		port = &tcp->th_sport;
967 		pr = "udp";
968 	}
969 
970 	*port = getportnum(pr, *arg);
971 	free(*arg);
972 	*arg = NULL;
973 }
974 
975 
976 void set_tcpdport(char **arg)
977 {
978 	u_short *port;
979 	char *pr;
980 
981 	if (ip->ip_p == IPPROTO_UDP) {
982 		port = &udp->uh_dport;
983 		pr = "udp";
984 	} else {
985 		port = &tcp->th_dport;
986 		pr = "udp";
987 	}
988 
989 	*port = getportnum(pr, *arg);
990 	free(*arg);
991 	*arg = NULL;
992 }
993 
994 
995 void set_tcpseq(char **arg)
996 {
997 	tcp->th_seq = htonl(strtol(*arg, NULL, 0));
998 	free(*arg);
999 	*arg = NULL;
1000 }
1001 
1002 
1003 void set_tcpack(char **arg)
1004 {
1005 	tcp->th_ack = htonl(strtol(*arg, NULL, 0));
1006 	free(*arg);
1007 	*arg = NULL;
1008 }
1009 
1010 
1011 void set_tcpoff(char **arg)
1012 {
1013 	int	off;
1014 
1015 	off = strtol(*arg, NULL, 0);
1016 	inc_anipheaders((off - tcp->th_off) << 2);
1017 	tcp->th_off = off;
1018 	free(*arg);
1019 	*arg = NULL;
1020 }
1021 
1022 
1023 void set_tcpurp(char **arg)
1024 {
1025 	tcp->th_urp = htons(strtol(*arg, NULL, 0));
1026 	free(*arg);
1027 	*arg = NULL;
1028 }
1029 
1030 
1031 void set_tcpwin(char **arg)
1032 {
1033 	tcp->th_win = htons(strtol(*arg, NULL, 0));
1034 	free(*arg);
1035 	*arg = NULL;
1036 }
1037 
1038 
1039 void set_tcpsum(char **arg)
1040 {
1041 	tcp->th_sum = strtol(*arg, NULL, 0);
1042 	free(*arg);
1043 	*arg = NULL;
1044 }
1045 
1046 
1047 void set_tcpflags(char **arg)
1048 {
1049 	static	char	flags[] = "ASURPF";
1050 	static	int	flagv[] = { TH_ACK, TH_SYN, TH_URG, TH_RST, TH_PUSH,
1051 				    TH_FIN } ;
1052 	char *s, *t;
1053 
1054 	for (s = *arg; *s; s++)
1055 		if (!(t = strchr(flags, *s))) {
1056 			if (s - *arg) {
1057 				fprintf(stderr, "unknown TCP flag %c\n", *s);
1058 				break;
1059 			}
1060 			tcp->th_flags = strtol(*arg, NULL, 0);
1061 			break;
1062 		} else
1063 			tcp->th_flags |= flagv[t - flags];
1064 	free(*arg);
1065 	*arg = NULL;
1066 }
1067 
1068 
1069 void set_tcpopt(int state, char **arg)
1070 {
1071 	u_char *s;
1072 	int val, len, val2, pad, optval;
1073 
1074 	if (arg && *arg)
1075 		val = atoi(*arg);
1076 	else
1077 		val = 0;
1078 
1079 	s = (u_char *)tcp + sizeof(*tcp) + canip->ah_optlen;
1080 	switch (state)
1081 	{
1082 	case IL_TCPO_EOL :
1083 		optval = 0;
1084 		len = 1;
1085 		break;
1086 	case IL_TCPO_NOP :
1087 		optval = 1;
1088 		len = 1;
1089 		break;
1090 	case IL_TCPO_MSS :
1091 		optval = 2;
1092 		len = 4;
1093 		break;
1094 	case IL_TCPO_WSCALE :
1095 		optval = 3;
1096 		len = 3;
1097 		break;
1098 	case IL_TCPO_TS :
1099 		optval = 8;
1100 		len = 10;
1101 		break;
1102 	default :
1103 		optval = 0;
1104 		len = 0;
1105 		break;
1106 	}
1107 
1108 	if (len > 1) {
1109 		/*
1110 		 * prepend padding - if required.
1111 		 */
1112 		if (len & 3)
1113 			for (pad = 4 - (len & 3); pad; pad--) {
1114 				*s++ = 1;
1115 				canip->ah_optlen++;
1116 			}
1117 		/*
1118 		 * build tcp option
1119 		 */
1120 		*s++ = (u_char)optval;
1121 		*s++ = (u_char)len;
1122 		if (len > 2) {
1123 			if (len == 3) {		/* 1 byte - char */
1124 				*s++ = (u_char)val;
1125 			} else if (len == 4) {	/* 2 bytes - short */
1126 				*s++ = (u_char)((val >> 8) & 0xff);
1127 				*s++ = (u_char)(val & 0xff);
1128 			} else if (len >= 6) {	/* 4 bytes - long */
1129 				val2 = htonl(val);
1130 				bcopy((char *)&val2, s, 4);
1131 			}
1132 			s += (len - 2);
1133 		}
1134 	} else
1135 		*s++ = (u_char)optval;
1136 
1137 	canip->ah_lastopt = optval;
1138 	canip->ah_optlen += len;
1139 
1140 	if (arg && *arg) {
1141 		free(*arg);
1142 		*arg = NULL;
1143 	}
1144 }
1145 
1146 
1147 void end_tcpopt(void)
1148 {
1149 	int pad;
1150 	char *s = (char *)tcp;
1151 
1152 	s += sizeof(*tcp) + canip->ah_optlen;
1153 	/*
1154 	 * pad out so that we have a multiple of 4 bytes in size fo the
1155 	 * options.  make sure last byte is EOL.
1156 	 */
1157 	if (canip->ah_optlen & 3) {
1158 		if (canip->ah_lastopt != 1) {
1159 			for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) {
1160 				*s++ = 1;
1161 				canip->ah_optlen++;
1162 			}
1163 			canip->ah_optlen++;
1164 		} else {
1165 			s -= 1;
1166 
1167 			for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) {
1168 				*s++ = 1;
1169 				canip->ah_optlen++;
1170 			}
1171 		}
1172 		*s++ = 0;
1173 	}
1174 	tcp->th_off = (sizeof(*tcp) + canip->ah_optlen) >> 2;
1175 	inc_anipheaders(canip->ah_optlen);
1176 }
1177 
1178 
1179 void new_udpheader(void)
1180 {
1181 	if ((ip->ip_p) && (ip->ip_p != IPPROTO_UDP)) {
1182 		fprintf(stderr, "protocol %d specified with UDP!\n", ip->ip_p);
1183 		return;
1184 	}
1185 	ip->ip_p = IPPROTO_UDP;
1186 
1187 	udp = (udphdr_t *)new_header(IPPROTO_UDP);
1188 	udp->uh_ulen = sizeof(*udp);
1189 }
1190 
1191 
1192 void set_udplen(arg)
1193 char **arg;
1194 {
1195 	int len;
1196 
1197 	len = strtol(*arg, NULL, 0);
1198 	inc_anipheaders(len - udp->uh_ulen);
1199 	udp->uh_ulen = len;
1200 	free(*arg);
1201 	*arg = NULL;
1202 }
1203 
1204 
1205 void set_udpsum(char **arg)
1206 {
1207 	udp->uh_sum = strtol(*arg, NULL, 0);
1208 	free(*arg);
1209 	*arg = NULL;
1210 }
1211 
1212 
1213 void prep_packet(void)
1214 {
1215 	iface_t *ifp;
1216 	struct in_addr gwip;
1217 
1218 	ifp = sending.snd_if;
1219 	if (!ifp) {
1220 		fprintf(stderr, "no interface defined for sending!\n");
1221 		return;
1222 	}
1223 	if (ifp->if_fd == -1)
1224 		ifp->if_fd = initdevice(ifp->if_name, 5);
1225 	gwip = sending.snd_gw;
1226 	if (!gwip.s_addr) {
1227 		if (aniphead == NULL) {
1228 			fprintf(stderr,
1229 				"no destination address defined for sending\n");
1230 			return;
1231 		}
1232 		gwip = aniphead->ah_ip->ip_dst;
1233 	}
1234 	(void) send_ip(ifp->if_fd, ifp->if_MTU, (ip_t *)ipbuffer, gwip, 2);
1235 }
1236 
1237 
1238 void packet_done(void)
1239 {
1240 	char    outline[80];
1241 	int     i, j, k;
1242 	u_char  *s = (u_char *)ipbuffer, *t = (u_char *)outline;
1243 
1244 	if (opts & OPT_VERBOSE) {
1245 		ip->ip_len = htons(ip->ip_len);
1246 		for (i = ntohs(ip->ip_len), j = 0; i; i--, j++, s++) {
1247 			if (j && !(j & 0xf)) {
1248 				*t++ = '\n';
1249 				*t = '\0';
1250 				fputs(outline, stdout);
1251 				fflush(stdout);
1252 				t = (u_char *)outline;
1253 				*t = '\0';
1254 			}
1255 			sprintf((char *)t, "%02x", *s & 0xff);
1256 			t += 2;
1257 			if (!((j + 1) & 0xf)) {
1258 				s -= 15;
1259 				sprintf((char *)t, "	");
1260 				t += 8;
1261 				for (k = 16; k; k--, s++)
1262 					*t++ = (isprint(*s) ? *s : '.');
1263 				s--;
1264 			}
1265 
1266 			if ((j + 1) & 0xf)
1267 				*t++ = ' ';;
1268 		}
1269 
1270 		if (j & 0xf) {
1271 			for (k = 16 - (j & 0xf); k; k--) {
1272 				*t++ = ' ';
1273 				*t++ = ' ';
1274 				*t++ = ' ';
1275 			}
1276 			sprintf((char *)t, "       ");
1277 			t += 7;
1278 			s -= j & 0xf;
1279 			for (k = j & 0xf; k; k--, s++)
1280 				*t++ = (isprint(*s) ? *s : '.');
1281 			*t++ = '\n';
1282 			*t = '\0';
1283 		}
1284 		fputs(outline, stdout);
1285 		fflush(stdout);
1286 		ip->ip_len = ntohs(ip->ip_len);
1287 	}
1288 
1289 	prep_packet();
1290 	free_aniplist();
1291 }
1292 
1293 
1294 void new_interface(void)
1295 {
1296 	cifp = (iface_t *)calloc(1, sizeof(iface_t));
1297 	*iftail = cifp;
1298 	iftail = &cifp->if_next;
1299 	cifp->if_fd = -1;
1300 }
1301 
1302 
1303 void check_interface(void)
1304 {
1305 	if (!cifp->if_name || !*cifp->if_name)
1306 		fprintf(stderr, "No interface name given!\n");
1307 	if (!cifp->if_MTU || !*cifp->if_name)
1308 		fprintf(stderr, "Interface %s has an MTU of 0!\n",
1309 			cifp->if_name);
1310 }
1311 
1312 
1313 void set_ifname(char **arg)
1314 {
1315 	cifp->if_name = *arg;
1316 	*arg = NULL;
1317 }
1318 
1319 
1320 void set_ifmtu(int arg)
1321 {
1322 	cifp->if_MTU = arg;
1323 }
1324 
1325 
1326 void set_ifv4addr(char **arg)
1327 {
1328 	cifp->if_addr = getipv4addr(*arg);
1329 	free(*arg);
1330 	*arg = NULL;
1331 }
1332 
1333 
1334 void set_ifeaddr(char **arg)
1335 {
1336 	(void) geteaddr(*arg, &cifp->if_eaddr);
1337 	free(*arg);
1338 	*arg = NULL;
1339 }
1340 
1341 
1342 void new_arp(void)
1343 {
1344 	carp = (arp_t *)calloc(1, sizeof(arp_t));
1345 	*arptail = carp;
1346 	arptail = &carp->arp_next;
1347 }
1348 
1349 
1350 void set_arpeaddr(char **arg)
1351 {
1352 	(void) geteaddr(*arg, &carp->arp_eaddr);
1353 	free(*arg);
1354 	*arg = NULL;
1355 }
1356 
1357 
1358 void set_arpv4addr(char **arg)
1359 {
1360 	carp->arp_addr = getipv4addr(*arg);
1361 	free(*arg);
1362 	*arg = NULL;
1363 }
1364 
1365 
1366 int arp_getipv4(char *ip, char *addr)
1367 {
1368 	arp_t *a;
1369 
1370 	for (a = arplist; a; a = a->arp_next)
1371 		if (!bcmp(ip, (char *)&a->arp_addr, 4)) {
1372 			bcopy((char *)&a->arp_eaddr, addr, 6);
1373 			return(0);
1374 		}
1375 	return(-1);
1376 }
1377 
1378 
1379 void reset_send(void)
1380 {
1381 	sending.snd_if = iflist;
1382 	sending.snd_gw = defrouter;
1383 }
1384 
1385 
1386 void set_sendif(char **arg)
1387 {
1388 	iface_t	*ifp;
1389 
1390 	for (ifp = iflist; ifp; ifp = ifp->if_next)
1391 		if (ifp->if_name && !strcmp(ifp->if_name, *arg))
1392 			break;
1393 	sending.snd_if = ifp;
1394 	if (!ifp)
1395 		fprintf(stderr, "couldn't find interface %s\n", *arg);
1396 	free(*arg);
1397 	*arg = NULL;
1398 }
1399 
1400 
1401 void set_sendvia(char **arg)
1402 {
1403 	sending.snd_gw = getipv4addr(*arg);
1404 	free(*arg);
1405 	*arg = NULL;
1406 }
1407 
1408 
1409 void set_defaultrouter(char **arg)
1410 {
1411 	defrouter = getipv4addr(*arg);
1412 	free(*arg);
1413 	*arg = NULL;
1414 }
1415 
1416 
1417 void new_icmpheader(void)
1418 {
1419 	if ((ip->ip_p) && (ip->ip_p != IPPROTO_ICMP)) {
1420 		fprintf(stderr, "protocol %d specified with ICMP!\n",
1421 			ip->ip_p);
1422 		return;
1423 	}
1424 	ip->ip_p = IPPROTO_ICMP;
1425 	icmp = (icmphdr_t *)new_header(IPPROTO_ICMP);
1426 }
1427 
1428 
1429 void set_icmpcode(int code)
1430 {
1431 	icmp->icmp_code = code;
1432 }
1433 
1434 
1435 void set_icmptype(int type)
1436 {
1437 	icmp->icmp_type = type;
1438 }
1439 
1440 
1441 void set_icmpcodetok(char **code)
1442 {
1443 	char	*s;
1444 	int	i;
1445 
1446 	for (i = 0; (s = icmpcodes[i]); i++)
1447 		if (!strcmp(s, *code)) {
1448 			icmp->icmp_code = i;
1449 			break;
1450 		}
1451 	if (!s)
1452 		fprintf(stderr, "unknown ICMP code %s\n", *code);
1453 	free(*code);
1454 	*code = NULL;
1455 }
1456 
1457 
1458 void set_icmptypetok(char **type)
1459 {
1460 	char	*s;
1461 	int	i, done = 0;
1462 
1463 	for (i = 0; !(s = icmptypes[i]) || strcmp(s, "END"); i++)
1464 		if (s && !strcmp(s, *type)) {
1465 			icmp->icmp_type = i;
1466 			done = 1;
1467 			break;
1468 		}
1469 	if (!done)
1470 		fprintf(stderr, "unknown ICMP type %s\n", *type);
1471 	free(*type);
1472 	*type = NULL;
1473 }
1474 
1475 
1476 void set_icmpid(int arg)
1477 {
1478 	icmp->icmp_id = htons(arg);
1479 }
1480 
1481 
1482 void set_icmpseq(int arg)
1483 {
1484 	icmp->icmp_seq = htons(arg);
1485 }
1486 
1487 
1488 void set_icmpotime(int arg)
1489 {
1490 	icmp->icmp_otime = htonl(arg);
1491 }
1492 
1493 
1494 void set_icmprtime(int arg)
1495 {
1496 	icmp->icmp_rtime = htonl(arg);
1497 }
1498 
1499 
1500 void set_icmpttime(int arg)
1501 {
1502 	icmp->icmp_ttime = htonl(arg);
1503 }
1504 
1505 
1506 void set_icmpmtu(int arg)
1507 {
1508 	icmp->icmp_nextmtu = htons(arg);
1509 }
1510 
1511 
1512 void set_redir(int redir, char **arg)
1513 {
1514 	icmp->icmp_code = redir;
1515 	icmp->icmp_gwaddr = getipv4addr(*arg);
1516 	free(*arg);
1517 	*arg = NULL;
1518 }
1519 
1520 
1521 void set_icmppprob(int num)
1522 {
1523 	icmp->icmp_pptr = num;
1524 }
1525 
1526 
1527 void new_ipv4opt(void)
1528 {
1529 	new_header(-2);
1530 }
1531 
1532 
1533 void add_ipopt(int state, void *ptr)
1534 {
1535 	struct ipopt_names *io;
1536 	struct statetoopt *sto;
1537 	char numbuf[16], *arg, **param = ptr;
1538 	int inc, hlen;
1539 
1540 	if (state == IL_IPO_RR || state == IL_IPO_SATID) {
1541 		if (param)
1542 			snprintf(numbuf, sizeof(numbuf), "%d", *(int *)param);
1543 		else
1544 			strcpy(numbuf, "0");
1545 		arg = numbuf;
1546 	} else
1547 		arg = param ? *param : NULL;
1548 
1549 	if (canip->ah_next) {
1550 		fprintf(stderr, "cannot specify options after data body\n");
1551 		return;
1552 	}
1553 	for (sto = toipopts; sto->sto_st; sto++)
1554 		if (sto->sto_st == state)
1555 			break;
1556 	if (!sto->sto_st) {
1557 		fprintf(stderr, "No mapping for state %d to IP option\n",
1558 			state);
1559 		return;
1560 	}
1561 
1562 	hlen = sizeof(ip_t) + canip->ah_optlen;
1563 	for (io = ionames; io->on_name; io++)
1564 		if (io->on_value == sto->sto_op)
1565 			break;
1566 	canip->ah_lastopt = io->on_value;
1567 
1568 	if (io->on_name) {
1569 		inc = addipopt((char *)ip + hlen, io, hlen - sizeof(ip_t),arg);
1570 		if (inc > 0) {
1571 			while (inc & 3) {
1572 				((char *)ip)[sizeof(*ip) + inc] = IPOPT_NOP;
1573 				canip->ah_lastopt = IPOPT_NOP;
1574 				inc++;
1575 			}
1576 			hlen += inc;
1577 		}
1578 	}
1579 
1580 	canip->ah_optlen = hlen - sizeof(ip_t);
1581 
1582 	if (state != IL_IPO_RR && state != IL_IPO_SATID)
1583 		if (param && *param) {
1584 			free(*param);
1585 			*param = NULL;
1586 		}
1587 	sclass = NULL;
1588 }
1589 
1590 
1591 void end_ipopt(void)
1592 {
1593 	int pad;
1594 	char *s, *buf = (char *)ip;
1595 
1596 	/*
1597 	 * pad out so that we have a multiple of 4 bytes in size fo the
1598 	 * options.  make sure last byte is EOL.
1599 	 */
1600 	if (canip->ah_lastopt == IPOPT_NOP) {
1601 		buf[sizeof(*ip) + canip->ah_optlen - 1] = IPOPT_EOL;
1602 	} else if (canip->ah_lastopt != IPOPT_EOL) {
1603 		s = buf + sizeof(*ip) + canip->ah_optlen;
1604 
1605 		for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) {
1606 			*s++ = IPOPT_NOP;
1607 			*s = IPOPT_EOL;
1608 			canip->ah_optlen++;
1609 		}
1610 		canip->ah_optlen++;
1611 	} else {
1612 		s = buf + sizeof(*ip) + canip->ah_optlen - 1;
1613 
1614 		for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) {
1615 			*s++ = IPOPT_NOP;
1616 			*s = IPOPT_EOL;
1617 			canip->ah_optlen++;
1618 		}
1619 	}
1620 	ip->ip_hl = (sizeof(*ip) + canip->ah_optlen) >> 2;
1621 	inc_anipheaders(canip->ah_optlen);
1622 	free_anipheader();
1623 }
1624 
1625 
1626 void set_secclass(char **arg)
1627 {
1628 	sclass = *arg;
1629 	*arg = NULL;
1630 }
1631 
1632 
1633 void free_anipheader(void)
1634 {
1635 	aniphdr_t *aip;
1636 
1637 	aip = canip;
1638 	if ((canip = aip->ah_prev)) {
1639 		canip->ah_next = NULL;
1640 		aniptail = &canip->ah_next;
1641 	}
1642 
1643 	if (canip)
1644 		free(aip);
1645 }
1646 
1647 
1648 void end_ipv4(void)
1649 {
1650 	aniphdr_t *aip;
1651 
1652 	ip->ip_sum = 0;
1653 	ip->ip_len = htons(ip->ip_len);
1654 	ip->ip_sum = chksum((u_short *)ip, ip->ip_hl << 2);
1655 	ip->ip_len = ntohs(ip->ip_len);
1656 	free_anipheader();
1657 	for (aip = aniphead, ip = NULL; aip; aip = aip->ah_next)
1658 		if (aip->ah_p == IPPROTO_IP)
1659 			ip = aip->ah_ip;
1660 }
1661 
1662 
1663 void end_icmp(void)
1664 {
1665 	aniphdr_t *aip;
1666 
1667 	icmp->icmp_cksum = 0;
1668 	icmp->icmp_cksum = chksum((u_short *)icmp, canip->ah_len);
1669 	free_anipheader();
1670 	for (aip = aniphead, icmp = NULL; aip; aip = aip->ah_next)
1671 		if (aip->ah_p == IPPROTO_ICMP)
1672 			icmp = aip->ah_icmp;
1673 }
1674 
1675 
1676 void end_udp(void)
1677 {
1678 	u_long	sum;
1679 	aniphdr_t *aip;
1680 	ip_t	iptmp;
1681 
1682 	bzero((char *)&iptmp, sizeof(iptmp));
1683 	iptmp.ip_p = ip->ip_p;
1684 	iptmp.ip_src = ip->ip_src;
1685 	iptmp.ip_dst = ip->ip_dst;
1686 	iptmp.ip_len = htons(ip->ip_len - (ip->ip_hl << 2));
1687 	sum = p_chksum((u_short *)&iptmp, (u_int)sizeof(iptmp));
1688 	udp->uh_ulen = htons(udp->uh_ulen);
1689 	udp->uh_sum = c_chksum((u_short *)udp, (u_int)ntohs(iptmp.ip_len), sum);
1690 	free_anipheader();
1691 	for (aip = aniphead, udp = NULL; aip; aip = aip->ah_next)
1692 		if (aip->ah_p == IPPROTO_UDP)
1693 			udp = aip->ah_udp;
1694 }
1695 
1696 
1697 void end_tcp(void)
1698 {
1699 	u_long	sum;
1700 	aniphdr_t *aip;
1701 	ip_t	iptmp;
1702 
1703 	bzero((char *)&iptmp, sizeof(iptmp));
1704 	iptmp.ip_p = ip->ip_p;
1705 	iptmp.ip_src = ip->ip_src;
1706 	iptmp.ip_dst = ip->ip_dst;
1707 	iptmp.ip_len = htons(ip->ip_len - (ip->ip_hl << 2));
1708 	sum = p_chksum((u_short *)&iptmp, (u_int)sizeof(iptmp));
1709 	tcp->th_sum = 0;
1710 	tcp->th_sum = c_chksum((u_short *)tcp, (u_int)ntohs(iptmp.ip_len), sum);
1711 	free_anipheader();
1712 	for (aip = aniphead, tcp = NULL; aip; aip = aip->ah_next)
1713 		if (aip->ah_p == IPPROTO_TCP)
1714 			tcp = aip->ah_tcp;
1715 }
1716 
1717 
1718 void end_data(void)
1719 {
1720 	free_anipheader();
1721 }
1722 
1723 
1724 void iplang(FILE *fp)
1725 {
1726 	yyin = fp;
1727 
1728 	yydebug = (opts & OPT_DEBUG) ? 1 : 0;
1729 
1730 	while (!feof(fp))
1731 		yyparse();
1732 }
1733 
1734 
1735 u_short	c_chksum(u_short *buf, u_int len, u_long init)
1736 {
1737 	u_long	sum = init;
1738 	int	nwords = len >> 1;
1739 
1740 	for(; nwords > 0; nwords--)
1741 		sum += *buf++;
1742 	sum = (sum>>16) + (sum & 0xffff);
1743 	sum += (sum >>16);
1744 	return(~sum);
1745 }
1746 
1747 
1748 u_long	p_chksum(u_short *buf, u_int len)
1749 {
1750 	u_long	sum = 0;
1751 	int	nwords = len >> 1;
1752 
1753 	for(; nwords > 0; nwords--)
1754 		sum += *buf++;
1755 	return(sum);
1756 }
1757