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