/* We want this to be readable, so only print out neccessary fields.
* Because that's the kind of world I want to live in. */voidprint_rule4(conststructipt_entry*e,structxtc_handle*h,constchar*chain,intcounters){conststructxt_entry_target*t;constchar*target_name;/* print counters for iptables-save */if(counters>0)printf("[%llu:%llu] ",(unsignedlonglong)e->counters.pcnt,(unsignedlonglong)e->counters.bcnt);/* print chain name */printf("-A %s",chain);/* Print IP part. */print_ip("-s",e->ip.src.s_addr,e->ip.smsk.s_addr,e->ip.invflags&IPT_INV_SRCIP);print_ip("-d",e->ip.dst.s_addr,e->ip.dmsk.s_addr,e->ip.invflags&IPT_INV_DSTIP);print_iface('i',e->ip.iniface,e->ip.iniface_mask,e->ip.invflags&IPT_INV_VIA_IN);print_iface('o',e->ip.outiface,e->ip.outiface_mask,e->ip.invflags&IPT_INV_VIA_OUT);print_proto(e->ip.proto,e->ip.invflags&XT_INV_PROTO);if(e->ip.flags&IPT_F_FRAG)printf("%s -f",e->ip.invflags&IPT_INV_FRAG?" !":"");/* Print matchinfo part */if(e->target_offset){IPT_MATCH_ITERATE(e,print_match_save,&e->ip);}/* print counters for iptables -R */if(counters<0)printf(" -c %llu %llu",(unsignedlonglong)e->counters.pcnt,(unsignedlonglong)e->counters.bcnt);/* Print target name and targinfo part */target_name=iptc_get_target(e,h);t=ipt_get_target((structipt_entry*)e);if(t->u.user.name[0]){conststructxtables_target*target=xtables_find_target(t->u.user.name,XTF_TRY_LOAD);if(!target){fprintf(stderr,"Can't find library for target `%s'\n",t->u.user.name);exit(1);}printf(" -j %s",target->alias?target->alias(t):target_name);if(target->save)target->save(&e->ip,t);else{/* If the target size is greater than xt_entry_target
* there is something to be saved, we just don't know
* how to print it */if(t->u.target_size!=sizeof(structxt_entry_target)){fprintf(stderr,"Target `%s' is missing ""save function\n",t->u.user.name);exit(1);}}}elseif(target_name&&(*target_name!='\0'))#ifdef IPT_F_GOTO
printf(" -%c %s",e->ip.flags&IPT_F_GOTO?'g':'j',target_name);#else
printf(" -j %s",target_name);#endif
printf("\n");}
structxt_entry_target{union{struct{__u16target_size;/* Used by userspace */charname[XT_EXTENSION_MAXNAMELEN];__u8revision;}user;struct{__u16target_size;/* Used inside the kernel */structxt_target*target;}kernel;/* Total length */__u16target_size;}u;unsignedchardata[0];};
structxtables_target{/*
* ABI/API version this module requires. Must be first member,
* as the rest of this struct may be subject to ABI changes.
*/constchar*version;structxtables_target*next;constchar*name;/* Real target behind this, if any. */constchar*real_name;/* Revision of target (0 by default). */u_int8_trevision;/* Extension flags */u_int8_text_flags;u_int16_tfamily;/* Size of target data. */size_tsize;/* Size of target data relevant for userspace comparison purposes */size_tuserspacesize;/* Function which prints out usage message. */void(*help)(void);/* Initialize the target. */void(*init)(structxt_entry_target*t);/* Function which parses command options; returns true if it
ate an option *//* entry is struct ipt_entry for example */int(*parse)(intc,char**argv,intinvert,unsignedint*flags,constvoid*entry,structxt_entry_target**targetinfo);/* Final check; exit if not ok. */void(*final_check)(unsignedintflags);/* Prints out the target iff non-NULL: put space at end */void(*print)(constvoid*ip,conststructxt_entry_target*target,intnumeric);/* Saves the targinfo in parsable form to stdout. */void(*save)(constvoid*ip,conststructxt_entry_target*target);/* Print target name or alias */constchar*(*alias)(conststructxt_entry_target*target);/* Pointer to list of extra command-line options */conststructoption*extra_opts;/* New parser */void(*x6_parse)(structxt_option_call*);void(*x6_fcheck)(structxt_fcheck_call*);conststructxt_option_entry*x6_options;size_tudata_size;/* Ignore these men behind the curtain: */void*udata;unsignedintoption_offset;structxt_entry_target*t;unsignedinttflags;unsignedintused;unsignedintloaded;/* simulate loading so options are merged properly */};
/* This structure defines each of the firewall rules. Consists of 3
parts which are 1) general IP header stuff 2) match specific
stuff 3) the target to perform if the rule matches */structipt_entry{structipt_ipip;/* Mark with fields that we care about. */unsignedintnfcache;/* Size of ipt_entry + matches */u_int16_ttarget_offset;/* Size of ipt_entry + matches + target */u_int16_tnext_offset;/* Back pointer */unsignedintcomefrom;/* Packet and byte counters. */structxt_counterscounters;/* The matches (if any), then the target. */unsignedcharelems[0];};
/* Yes, Virginia, you have to zero the padding. */structipt_ip{/* Source and destination IP addr */structin_addrsrc,dst;/* Mask for src and dest IP addr */structin_addrsmsk,dmsk;chariniface[IFNAMSIZ],outiface[IFNAMSIZ];unsignedchariniface_mask[IFNAMSIZ],outiface_mask[IFNAMSIZ];/* Protocol, 0 = ANY */u_int16_tproto;/* Flags word */u_int8_tflags;/* Inverse flags */u_int8_tinvflags;};
/* Values for "flag" field in struct ipt_ip (general ip structure). */#define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */#define IPT_F_GOTO 0x02 /* Set if jump is a goto */#define IPT_F_MASK 0x03 /* All possible flag bits mask. */`iptables/iptables.c#L1039-#L1067<https://git.netfilter.org/iptables/tree/iptables/iptables.c?id=482c6d3731e2681cb4baae835c294840300197e6#n1039>`_
..code-block::c:linenos:table:linenostart:1039/* print a given ip including mask if neccessary */staticvoidprint_ip(constchar*prefix,uint32_tip,uint32_tmask,intinvert){uint32_tbits,hmask=ntohl(mask);inti;if(!mask&&!ip&&!invert)return;printf("%s %s %u.%u.%u.%u",invert?" !":"",prefix,IP_PARTS(ip));if(mask==0xFFFFFFFFU){printf("/32");return;}i=32;bits=0xFFFFFFFEU;while(--i>=0&&hmask!=bits)bits<<=1;if(i>=0)printf("/%u",i);elseprintf("/%u.%u.%u.%u",IP_PARTS(mask));}`iptables/iptables.c#L989-#L1013<https://git.netfilter.org/iptables/tree/iptables/iptables.c?id=482c6d3731e2681cb4baae835c294840300197e6#n989>`_
..code-block::c:linenos:table:linenostart:989/* This assumes that mask is contiguous, and byte-bounded. */staticvoidprint_iface(charletter,constchar*iface,constunsignedchar*mask,intinvert){unsignedinti;if(mask[0]==0)return;printf("%s -%c ",invert?" !":"",letter);for(i=0;i<IFNAMSIZ;i++){if(mask[i]!=0){if(iface[i]!='\0')printf("%c",iface[i]);}else{/* we can access iface[i-1] here, because
* a few lines above we make sure that mask[0] != 0 */if(iface[i-1]!='\0')printf("+");break;}}}`iptables/iptables.c#L958-#L979<https://git.netfilter.org/iptables/tree/iptables/iptables.c?id=482c6d3731e2681cb4baae835c294840300197e6#n958>`_
..code-block::c:linenos:table:linenostart:958staticvoidprint_proto(uint16_tproto,intinvert){if(proto){unsignedinti;constchar*invertstr=invert?" !":"";conststructprotoent*pent=getprotobynumber(proto);if(pent){printf("%s -p %s",invertstr,pent->p_name);return;}for(i=0;xtables_chain_protos[i].name!=NULL;++i)if(xtables_chain_protos[i].num==proto){printf("%s -p %s",invertstr,xtables_chain_protos[i].name);return;}printf("%s -p %u",invertstr,proto);}}`include/linux/netfilter_ipv4/ip_tables.h#L58-#L60<https://git.netfilter.org/iptables/tree/include/linux/netfilter_ipv4/ip_tables.h?id=482c6d3731e2681cb4baae835c294840300197e6#n58>`_
..code-block::c:linenos:table:linenostart:58/* fn returns 0 to continue iteration */#define IPT_MATCH_ITERATE(e, fn, args...) \
XT_MATCH_ITERATE(struct ipt_entry, e, fn, ## args)
`include/linux/netfilter/x_tables.h#L126-#L143<https://git.netfilter.org/iptables/tree/include/linux/netfilter/x_tables.h?id=482c6d3731e2681cb4baae835c294840300197e6#n126>`_
..code-block::c:linenos:table:linenostart:126/* fn returns 0 to continue iteration */#define XT_MATCH_ITERATE(type, e, fn, args...) \
({ \
unsigned int __i; \
int __ret = 0; \
struct xt_entry_match *__m; \
\
for (__i = sizeof(type); \
__i < (e)->target_offset; \
__i += __m->u.match_size) { \
__m = (void *)e + __i; \
\
__ret = fn(__m , ## args); \
if (__ret != 0) \
break; \
} \
__ret; \
})
`iptables/iptables.c#L1015-#L1037<https://git.netfilter.org/iptables/tree/iptables/iptables.c?id=482c6d3731e2681cb4baae835c294840300197e6#n1015>`_
..code-block::c:linenos:table:linenostart:1015staticintprint_match_save(conststructxt_entry_match*e,conststructipt_ip*ip){conststructxtables_match*match=xtables_find_match(e->u.user.name,XTF_TRY_LOAD,NULL);if(match){printf(" -m %s",match->alias?match->alias(e):e->u.user.name);/* some matches don't provide a save function */if(match->save)match->save(ip,e);}else{if(e->u.match_size){fprintf(stderr,"Can't find library for match `%s'\n",e->u.user.name);exit(1);}}return0;}