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