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