ipfwadm_core.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:33k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* Minor modifications to fit on compatibility framework:
  2.    Rusty.Russell@rustcorp.com.au
  3. */
  4. #include <linux/config.h>
  5. #define CONFIG_IP_FIREWALL
  6. #define CONFIG_IP_FIREWALL_VERBOSE
  7. #define CONFIG_IP_MASQUERADE
  8. #define CONFIG_IP_ACCT
  9. #define CONFIG_IP_TRANSPARENT_PROXY
  10. #if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE)
  11. #define CONFIG_IP_FIREWALL_NETLINK
  12. #endif
  13. /*
  14.  * IP firewalling code. This is taken from 4.4BSD. Please note the
  15.  * copyright message below. As per the GPL it must be maintained
  16.  * and the licenses thus do not conflict. While this port is subject
  17.  * to the GPL I also place my modifications under the original
  18.  * license in recognition of the original copyright.
  19.  * -- Alan Cox.
  20.  *
  21.  * $Id: ipfwadm_core.c,v 1.9.2.2 2002/01/24 15:50:42 davem Exp $
  22.  *
  23.  * Ported from BSD to Linux,
  24.  * Alan Cox 22/Nov/1994.
  25.  * Zeroing /proc and other additions
  26.  * Jos Vos 4/Feb/1995.
  27.  * Merged and included the FreeBSD-Current changes at Ugen's request
  28.  * (but hey it's a lot cleaner now). Ugen would prefer in some ways
  29.  * we waited for his final product but since Linux 1.2.0 is about to
  30.  * appear it's not practical - Read: It works, it's not clean but please
  31.  * don't consider it to be his standard of finished work.
  32.  * Alan Cox 12/Feb/1995
  33.  * Porting bidirectional entries from BSD, fixing accounting issues,
  34.  * adding struct ip_fwpkt for checking packets with interface address
  35.  * Jos Vos 5/Mar/1995.
  36.  * Established connections (ACK check), ACK check on bidirectional rules,
  37.  * ICMP type check.
  38.  * Wilfred Mollenvanger 7/7/1995.
  39.  * TCP attack protection.
  40.  * Alan Cox 25/8/95, based on information from bugtraq.
  41.  * ICMP type printk, IP_FW_F_APPEND
  42.  * Bernd Eckenfels 1996-01-31
  43.  * Split blocking chain into input and output chains, add new "insert" and
  44.  * "append" commands to replace semi-intelligent "add" command, let "delete".
  45.  * only delete the first matching entry, use 0xFFFF (0xFF) as ports (ICMP
  46.  * types) when counting packets being 2nd and further fragments.
  47.  * Jos Vos <jos@xos.nl> 8/2/1996.
  48.  * Add support for matching on device names.
  49.  * Jos Vos <jos@xos.nl> 15/2/1996.
  50.  * Transparent proxying support.
  51.  * Willy Konynenberg <willy@xos.nl> 10/5/96.
  52.  * Make separate accounting on incoming and outgoing packets possible.
  53.  * Jos Vos <jos@xos.nl> 18/5/1996.
  54.  * Added trap out of bad frames.
  55.  * Alan Cox <alan@cymru.net> 17/11/1996
  56.  *
  57.  *
  58.  * Masquerading functionality
  59.  *
  60.  * Copyright (c) 1994 Pauline Middelink
  61.  *
  62.  * The pieces which added masquerading functionality are totally
  63.  * my responsibility and have nothing to with the original authors
  64.  * copyright or doing.
  65.  *
  66.  * Parts distributed under GPL.
  67.  *
  68.  * Fixes:
  69.  * Pauline Middelink : Added masquerading.
  70.  * Alan Cox : Fixed an error in the merge.
  71.  * Thomas Quinot : Fixed port spoofing.
  72.  * Alan Cox : Cleaned up retransmits in spoofing.
  73.  * Alan Cox : Cleaned up length setting.
  74.  * Wouter Gadeyne : Fixed masquerading support of ftp PORT commands
  75.  *
  76.  * Juan Jose Ciarlante : Masquerading code moved to ip_masq.c
  77.  * Andi Kleen : Print frag_offsets and the ip flags properly.
  78.  *
  79.  * All the real work was done by .....
  80.  *
  81.  */
  82. /*
  83.  * Copyright (c) 1993 Daniel Boulet
  84.  * Copyright (c) 1994 Ugen J.S.Antsilevich
  85.  *
  86.  * Redistribution and use in source forms, with and without modification,
  87.  * are permitted provided that this entire comment appears intact.
  88.  *
  89.  * Redistribution in binary form may occur without any restrictions.
  90.  * Obviously, it would be nice if you gave credit where credit is due
  91.  * but requiring it would be too onerous.
  92.  *
  93.  * This software is provided ``AS IS'' without any warranties of any kind.
  94.  */
  95. #include <asm/uaccess.h>
  96. #include <asm/system.h>
  97. #include <linux/types.h>
  98. #include <linux/kernel.h>
  99. #include <linux/sched.h>
  100. #include <linux/string.h>
  101. #include <linux/errno.h>
  102. #include <linux/module.h>
  103. #include <linux/socket.h>
  104. #include <linux/sockios.h>
  105. #include <linux/in.h>
  106. #include <linux/inet.h>
  107. #include <linux/netdevice.h>
  108. #include <linux/icmp.h>
  109. #include <linux/udp.h>
  110. #include <net/ip.h>
  111. #include <net/protocol.h>
  112. #include <net/route.h>
  113. #include <net/tcp.h>
  114. #include <net/udp.h>
  115. #include <net/sock.h>
  116. #include <net/icmp.h>
  117. #include <linux/netlink.h>
  118. #include <linux/init.h>
  119. #include <linux/netfilter_ipv4/ipfwadm_core.h>
  120. #include <linux/netfilter_ipv4/compat_firewall.h>
  121. #include <net/checksum.h>
  122. #include <linux/proc_fs.h>
  123. #include <linux/stat.h>
  124. #include <linux/version.h>
  125. /*
  126.  * Implement IP packet firewall
  127.  */
  128. #ifdef DEBUG_IP_FIREWALL
  129. #define dprintf1(a) printk(a)
  130. #define dprintf2(a1,a2) printk(a1,a2)
  131. #define dprintf3(a1,a2,a3) printk(a1,a2,a3)
  132. #define dprintf4(a1,a2,a3,a4) printk(a1,a2,a3,a4)
  133. #else
  134. #define dprintf1(a)
  135. #define dprintf2(a1,a2)
  136. #define dprintf3(a1,a2,a3)
  137. #define dprintf4(a1,a2,a3,a4)
  138. #endif
  139. #define print_ip(a)  printk("%u.%u.%u.%u", NIPQUAD(a));
  140. #ifdef DEBUG_IP_FIREWALL
  141. #define dprint_ip(a) print_ip(a)
  142. #else
  143. #define dprint_ip(a)
  144. #endif
  145. #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
  146. struct ip_fw *ip_fw_fwd_chain;
  147. struct ip_fw *ip_fw_in_chain;
  148. struct ip_fw *ip_fw_out_chain;
  149. struct ip_fw *ip_acct_chain;
  150. struct ip_fw *ip_masq_chain;
  151. static struct ip_fw **chains[] =
  152. {&ip_fw_fwd_chain, &ip_fw_in_chain, &ip_fw_out_chain, &ip_acct_chain,
  153.  &ip_masq_chain
  154. };
  155. #endif /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */
  156. #ifdef CONFIG_IP_FIREWALL
  157. int ip_fw_fwd_policy=IP_FW_F_ACCEPT;
  158. int ip_fw_in_policy=IP_FW_F_ACCEPT;
  159. int ip_fw_out_policy=IP_FW_F_ACCEPT;
  160. static int *policies[] =
  161. {&ip_fw_fwd_policy, &ip_fw_in_policy, &ip_fw_out_policy};
  162. #endif
  163. #ifdef CONFIG_IP_FIREWALL_NETLINK
  164. struct sock *ipfwsk;
  165. #endif
  166. /*
  167.  * Returns 1 if the port is matched by the vector, 0 otherwise
  168.  */
  169. extern inline int port_match(unsigned short *portptr,int nports,unsigned short port,int range_flag)
  170. {
  171. if (!nports)
  172. return 1;
  173. if ( range_flag )
  174. {
  175. if ( portptr[0] <= port && port <= portptr[1] )
  176. {
  177. return( 1 );
  178. }
  179. nports -= 2;
  180. portptr += 2;
  181. }
  182. while ( nports-- > 0 )
  183. {
  184. if ( *portptr++ == port )
  185. {
  186. return( 1 );
  187. }
  188. }
  189. return(0);
  190. }
  191. #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
  192. #ifdef CONFIG_IP_FIREWALL_VERBOSE
  193. /*
  194.  * VERY ugly piece of code which actually makes kernel printf for
  195.  *  matching packets.
  196.  */
  197. static char *chain_name(struct ip_fw *chain, int mode)
  198. {
  199. switch (mode) {
  200. case IP_FW_MODE_ACCT_IN: return "acct in";
  201. case IP_FW_MODE_ACCT_OUT: return "acct out";
  202. default:
  203. if (chain == ip_fw_fwd_chain)
  204. return "fw-fwd";
  205. else if (chain == ip_fw_in_chain)
  206. return "fw-in";
  207. else
  208. return "fw-out";
  209. }
  210. }
  211. static char *rule_name(struct ip_fw *f, int mode, char *buf)
  212. {
  213. if (mode == IP_FW_MODE_ACCT_IN || mode == IP_FW_MODE_ACCT_OUT)
  214. return "";
  215. if(f->fw_flg&IP_FW_F_ACCEPT) {
  216. if(f->fw_flg&IP_FW_F_REDIR) {
  217. sprintf(buf, "acc/r%d ", f->fw_pts[f->fw_nsp+f->fw_ndp]);
  218. return buf;
  219. } else if(f->fw_flg&IP_FW_F_MASQ)
  220. return "acc/masq ";
  221. else
  222. return "acc ";
  223. } else if(f->fw_flg&IP_FW_F_ICMPRPL) {
  224. return "rej ";
  225. } else {
  226. return "deny ";
  227. }
  228. }
  229. static void print_packet(struct iphdr *ip,
  230.  u16 src_port, u16 dst_port, u16 icmp_type,
  231.  char *chain, char *rule, char *devname)
  232. {
  233. __u32 *opt = (__u32 *) (ip + 1);
  234. int opti;
  235. __u16 foff = ntohs(ip->frag_off);
  236. printk(KERN_INFO "IP %s %s%s", chain, rule, devname);
  237. switch(ip->protocol)
  238. {
  239. case IPPROTO_TCP:
  240. printk(" TCP ");
  241. break;
  242. case IPPROTO_UDP:
  243. printk(" UDP ");
  244. break;
  245. case IPPROTO_ICMP:
  246. printk(" ICMP/%d ", icmp_type);
  247. break;
  248. default:
  249. printk(" PROTO=%d ", ip->protocol);
  250. break;
  251. }
  252. print_ip(ip->saddr);
  253. if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
  254. printk(":%hu", src_port);
  255. printk(" ");
  256. print_ip(ip->daddr);
  257. if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
  258. printk(":%hu", dst_port);
  259. printk(" L=%hu S=0x%2.2hX I=%hu FO=0x%4.4hX T=%hu",
  260.        ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
  261.        foff & IP_OFFSET, ip->ttl);
  262. if (foff & IP_DF) printk(" DF=1");
  263. if (foff & IP_MF) printk(" MF=1");
  264. for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
  265. printk(" O=0x%8.8X", *opt++);
  266. printk("n");
  267. }
  268. #endif
  269. /*
  270.  * Returns one of the generic firewall policies, like FW_ACCEPT.
  271.  * Also does accounting so you can feed it the accounting chain.
  272.  *
  273.  * The modes is either IP_FW_MODE_FW (normal firewall mode),
  274.  * IP_FW_MODE_ACCT_IN or IP_FW_MODE_ACCT_OUT (accounting mode,
  275.  * steps through the entire chain and handles fragments
  276.  * differently), or IP_FW_MODE_CHK (handles user-level check,
  277.  * counters are not updated).
  278.  */
  279. int ip_fw_chk(struct iphdr *ip, struct net_device *rif, __u16 *redirport,
  280.       struct ip_fw *chain, int policy, int mode)
  281. {
  282. struct ip_fw *f;
  283. struct tcphdr *tcp=(struct tcphdr *)((__u32 *)ip+ip->ihl);
  284. struct udphdr *udp=(struct udphdr *)((__u32 *)ip+ip->ihl);
  285. struct icmphdr *icmp=(struct icmphdr *)((__u32 *)ip+ip->ihl);
  286. __u32 src, dst;
  287. __u16 src_port=0xFFFF, dst_port=0xFFFF, icmp_type=0xFF;
  288. unsigned short f_prt=0, prt;
  289. char notcpsyn=0, notcpack=0, match;
  290. unsigned short offset;
  291. int answer;
  292. unsigned char tosand, tosxor;
  293. /*
  294.  * If the chain is empty follow policy. The BSD one
  295.  * accepts anything giving you a time window while
  296.  * flushing and rebuilding the tables.
  297.  */
  298. src = ip->saddr;
  299. dst = ip->daddr;
  300. /*
  301.  * This way we handle fragmented packets.
  302.  * we ignore all fragments but the first one
  303.  * so the whole packet can't be reassembled.
  304.  * This way we relay on the full info which
  305.  * stored only in first packet.
  306.  *
  307.  * Note that this theoretically allows partial packet
  308.  * spoofing. Not very dangerous but paranoid people may
  309.  * wish to play with this. It also allows the so called
  310.  * "fragment bomb" denial of service attack on some types
  311.  * of system.
  312.  */
  313. offset = ntohs(ip->frag_off) & IP_OFFSET;
  314. /*
  315.  * Don't allow a fragment of TCP 8 bytes in. Nobody
  316.  * normal causes this. Its a cracker trying to break
  317.  * in by doing a flag overwrite to pass the direction
  318.  * checks.
  319.  */
  320. if (offset == 1 && ip->protocol == IPPROTO_TCP)
  321. return FW_BLOCK;
  322. if (offset!=0 && !(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT)) &&
  323. (ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP ||
  324. ip->protocol == IPPROTO_ICMP))
  325. return FW_ACCEPT;
  326. /*
  327.  *  Header fragment for TCP is too small to check the bits.
  328.  */
  329. if(ip->protocol==IPPROTO_TCP && (ip->ihl<<2)+16 > ntohs(ip->tot_len))
  330. return FW_BLOCK;
  331. /*
  332.  * Too short.
  333.  *
  334.  * But only too short for a packet with ports...
  335.  */
  336. else if((ntohs(ip->tot_len)<8+(ip->ihl<<2))&&(ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP))
  337. return FW_BLOCK;
  338. src = ip->saddr;
  339. dst = ip->daddr;
  340. /*
  341.  * If we got interface from which packet came
  342.  * we can use the address directly. This is unlike
  343.  * 4.4BSD derived systems that have an address chain
  344.  * per device. We have a device per address with dummy
  345.  * devices instead.
  346.  */
  347. dprintf1("Packet ");
  348. switch(ip->protocol)
  349. {
  350. case IPPROTO_TCP:
  351. dprintf1("TCP ");
  352. /* ports stay 0xFFFF if it is not the first fragment */
  353. if (!offset) {
  354. src_port=ntohs(tcp->source);
  355. dst_port=ntohs(tcp->dest);
  356. if(!tcp->ack && !tcp->rst)
  357. /* We do NOT have ACK, value TRUE */
  358. notcpack=1;
  359. if(!tcp->syn || !notcpack)
  360. /* We do NOT have SYN, value TRUE */
  361. notcpsyn=1;
  362. }
  363. prt=IP_FW_F_TCP;
  364. break;
  365. case IPPROTO_UDP:
  366. dprintf1("UDP ");
  367. /* ports stay 0xFFFF if it is not the first fragment */
  368. if (!offset) {
  369. src_port=ntohs(udp->source);
  370. dst_port=ntohs(udp->dest);
  371. }
  372. prt=IP_FW_F_UDP;
  373. break;
  374. case IPPROTO_ICMP:
  375. /* icmp_type stays 255 if it is not the first fragment */
  376. if (!offset)
  377. icmp_type=(__u16)(icmp->type);
  378. dprintf2("ICMP:%d ",icmp_type);
  379. prt=IP_FW_F_ICMP;
  380. break;
  381. default:
  382. dprintf2("p=%d ",ip->protocol);
  383. prt=IP_FW_F_ALL;
  384. break;
  385. }
  386. #ifdef DEBUG_IP_FIREWALL
  387. dprint_ip(ip->saddr);
  388. if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)
  389. /* This will print 65535 when it is not the first fragment! */
  390. dprintf2(":%d ", src_port);
  391. dprint_ip(ip->daddr);
  392. if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)
  393. /* This will print 65535 when it is not the first fragment! */
  394. dprintf2(":%d ",dst_port);
  395. dprintf1("n");
  396. #endif
  397. for (f=chain;f;f=f->fw_next)
  398. {
  399. /*
  400.  * This is a bit simpler as we don't have to walk
  401.  * an interface chain as you do in BSD - same logic
  402.  * however.
  403.  */
  404. /*
  405.  * Match can become 0x01 (a "normal" match was found),
  406.  * 0x02 (a reverse match was found), and 0x03 (the
  407.  * IP addresses match in both directions).
  408.  * Now we know in which direction(s) we should look
  409.  * for a match for the TCP/UDP ports.  Both directions
  410.  * might match (e.g., when both addresses are on the
  411.  * same network for which an address/mask is given), but
  412.  * the ports might only match in one direction.
  413.  * This was obviously wrong in the original BSD code.
  414.  */
  415. match = 0x00;
  416. if ((src&f->fw_smsk.s_addr)==f->fw_src.s_addr
  417. &&  (dst&f->fw_dmsk.s_addr)==f->fw_dst.s_addr)
  418. /* normal direction */
  419. match |= 0x01;
  420. if ((f->fw_flg & IP_FW_F_BIDIR) &&
  421.     (dst&f->fw_smsk.s_addr)==f->fw_src.s_addr
  422. &&  (src&f->fw_dmsk.s_addr)==f->fw_dst.s_addr)
  423. /* reverse direction */
  424. match |= 0x02;
  425. if (!match)
  426. continue;
  427. /*
  428.  * Look for a VIA device match
  429.  */
  430. if(f->fw_viadev)
  431. {
  432. if(rif!=f->fw_viadev)
  433. continue; /* Mismatch */
  434. }
  435. /* This looks stupid, because we scan almost static
  436.    list, searching for static key. However, this way seems
  437.    to be only reasonable way of handling fw_via rules
  438.    (btw bsd makes the same thing).
  439.    It will not affect performance if you will follow
  440.    the following simple rules:
  441.    - if inteface is aliased, ALWAYS specify fw_viadev,
  442.      so that previous check will guarantee, that we will
  443.      not waste time when packet arrive on another interface.
  444.    - avoid using fw_via.s_addr if fw_via.s_addr is owned
  445.      by an aliased interface.
  446.                                                        --ANK
  447.  */
  448. if (f->fw_via.s_addr && rif) {
  449. struct in_ifaddr *ifa;
  450. if (rif->ip_ptr == NULL)
  451. continue; /* Mismatch */
  452. for (ifa = ((struct in_device*)(rif->ip_ptr))->ifa_list;
  453.      ifa; ifa = ifa->ifa_next) {
  454. if (ifa->ifa_local == f->fw_via.s_addr)
  455. goto ifa_ok;
  456. }
  457. continue; /* Mismatch */
  458. ifa_ok:;
  459. }
  460. /*
  461.  * Ok the chain addresses match.
  462.  */
  463. #ifdef CONFIG_IP_ACCT
  464. /*
  465.  * See if we're in accounting mode and only want to
  466.  * count incoming or outgoing packets.
  467.  */
  468. if (mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT) &&
  469.    ((mode == IP_FW_MODE_ACCT_IN && f->fw_flg&IP_FW_F_ACCTOUT) ||
  470.     (mode == IP_FW_MODE_ACCT_OUT && f->fw_flg&IP_FW_F_ACCTIN)))
  471. continue;
  472. #endif
  473. /*
  474.  * For all non-TCP packets and/or non-first fragments,
  475.  * notcpsyn and notcpack will always be FALSE,
  476.  * so the IP_FW_F_TCPSYN and IP_FW_F_TCPACK flags
  477.  * are actually ignored for these packets.
  478.  */
  479. if((f->fw_flg&IP_FW_F_TCPSYN) && notcpsyn)
  480.   continue;
  481. if((f->fw_flg&IP_FW_F_TCPACK) && notcpack)
  482.   continue;
  483. f_prt=f->fw_flg&IP_FW_F_KIND;
  484. if (f_prt!=IP_FW_F_ALL)
  485. {
  486. /*
  487.  * Specific firewall - packet's protocol
  488.  * must match firewall's.
  489.  */
  490. if(prt!=f_prt)
  491. continue;
  492. if((prt==IP_FW_F_ICMP &&
  493. ! port_match(&f->fw_pts[0], f->fw_nsp,
  494. icmp_type,f->fw_flg&IP_FW_F_SRNG)) ||
  495.     !(prt==IP_FW_F_ICMP || ((match & 0x01) &&
  496. port_match(&f->fw_pts[0], f->fw_nsp, src_port,
  497. f->fw_flg&IP_FW_F_SRNG) &&
  498. port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, dst_port,
  499. f->fw_flg&IP_FW_F_DRNG)) || ((match & 0x02) &&
  500. port_match(&f->fw_pts[0], f->fw_nsp, dst_port,
  501. f->fw_flg&IP_FW_F_SRNG) &&
  502. port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, src_port,
  503. f->fw_flg&IP_FW_F_DRNG))))
  504. {
  505. continue;
  506. }
  507. }
  508. #ifdef CONFIG_IP_FIREWALL_VERBOSE
  509. if (f->fw_flg & IP_FW_F_PRN)
  510. {
  511. char buf[16];
  512. print_packet(ip, src_port, dst_port, icmp_type,
  513.      chain_name(chain, mode),
  514.      rule_name(f, mode, buf),
  515.      rif ? rif->name : "-");
  516. }
  517. #endif
  518. if (mode != IP_FW_MODE_CHK) {
  519. f->fw_bcnt+=ntohs(ip->tot_len);
  520. f->fw_pcnt++;
  521. }
  522. if (!(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT)))
  523. break;
  524. } /* Loop */
  525. if (!(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT))) {
  526. /*
  527.  * We rely on policy defined in the rejecting entry or, if no match
  528.  * was found, we rely on the general policy variable for this type
  529.  * of firewall.
  530.  */
  531. if (f!=NULL) {
  532. policy=f->fw_flg;
  533. tosand=f->fw_tosand;
  534. tosxor=f->fw_tosxor;
  535. } else {
  536. tosand=0xFF;
  537. tosxor=0x00;
  538. }
  539. if (policy&IP_FW_F_ACCEPT) {
  540. /* Adjust priority and recompute checksum */
  541. __u8 old_tos = ip->tos;
  542. ip->tos = (old_tos & tosand) ^ tosxor;
  543. if (ip->tos != old_tos)
  544.   ip_send_check(ip);
  545. #ifdef CONFIG_IP_TRANSPARENT_PROXY
  546. if (policy&IP_FW_F_REDIR) {
  547. if (redirport)
  548. if ((*redirport = htons(f->fw_pts[f->fw_nsp+f->fw_ndp])) == 0) {
  549. /* Wildcard redirection.
  550.  * Note that redirport will become
  551.  * 0xFFFF for non-TCP/UDP packets.
  552.  */
  553. *redirport = htons(dst_port);
  554. }
  555. answer = FW_REDIRECT;
  556. } else
  557. #endif
  558. #ifdef CONFIG_IP_MASQUERADE
  559. if (policy&IP_FW_F_MASQ)
  560. answer = FW_MASQUERADE;
  561. else
  562. #endif
  563. answer = FW_ACCEPT;
  564. } else if(policy&IP_FW_F_ICMPRPL)
  565. answer = FW_REJECT;
  566. else
  567. answer = FW_BLOCK;
  568. #ifdef CONFIG_IP_FIREWALL_NETLINK
  569. if((policy&IP_FW_F_PRN) && (answer == FW_REJECT || answer == FW_BLOCK))
  570. {
  571. struct sk_buff *skb=alloc_skb(128, GFP_ATOMIC);
  572. if(skb)
  573. {
  574. int len = min_t(unsigned int,
  575.       128, ntohs(ip->tot_len));
  576. skb_put(skb,len);
  577. memcpy(skb->data,ip,len);
  578. if(netlink_post(NETLINK_FIREWALL, skb))
  579. kfree_skb(skb);
  580. }
  581. }
  582. #endif
  583. return answer;
  584. } else
  585. /* we're doing accounting, always ok */
  586. return 0;
  587. }
  588. static void zero_fw_chain(struct ip_fw *chainptr)
  589. {
  590. struct ip_fw *ctmp=chainptr;
  591. while(ctmp)
  592. {
  593. ctmp->fw_pcnt=0L;
  594. ctmp->fw_bcnt=0L;
  595. ctmp=ctmp->fw_next;
  596. }
  597. }
  598. static void free_fw_chain(struct ip_fw *volatile* chainptr)
  599. {
  600. unsigned long flags;
  601. save_flags(flags);
  602. cli();
  603. while ( *chainptr != NULL )
  604. {
  605. struct ip_fw *ftmp;
  606. ftmp = *chainptr;
  607. *chainptr = ftmp->fw_next;
  608. kfree(ftmp);
  609. MOD_DEC_USE_COUNT;
  610. }
  611. restore_flags(flags);
  612. }
  613. /* Volatiles to keep some of the compiler versions amused */
  614. static int insert_in_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl,int len)
  615. {
  616. struct ip_fw *ftmp;
  617. unsigned long flags;
  618. save_flags(flags);
  619. ftmp = kmalloc( sizeof(struct ip_fw), GFP_ATOMIC );
  620. if ( ftmp == NULL )
  621. {
  622. #ifdef DEBUG_IP_FIREWALL
  623. printk("ip_fw_ctl:  malloc said non");
  624. #endif
  625. return( ENOMEM );
  626. }
  627. memcpy(ftmp, frwl, len);
  628. /*
  629.  * Allow the more recent "minimise cost" flag to be
  630.  * set. [Rob van Nieuwkerk]
  631.  */
  632. ftmp->fw_tosand |= 0x01;
  633. ftmp->fw_tosxor &= 0xFE;
  634. ftmp->fw_pcnt=0L;
  635. ftmp->fw_bcnt=0L;
  636. cli();
  637. if ((ftmp->fw_vianame)[0]) {
  638. if (!(ftmp->fw_viadev = dev_get_by_name(ftmp->fw_vianame)))
  639. ftmp->fw_viadev = (struct net_device *) -1;
  640. } else
  641. ftmp->fw_viadev = NULL;
  642. ftmp->fw_next = *chainptr;
  643.         *chainptr=ftmp;
  644. restore_flags(flags);
  645. MOD_INC_USE_COUNT;
  646. return(0);
  647. }
  648. static int append_to_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl,int len)
  649. {
  650. struct ip_fw *ftmp;
  651. struct ip_fw *chtmp=NULL;
  652. struct ip_fw *volatile chtmp_prev=NULL;
  653. unsigned long flags;
  654. save_flags(flags);
  655. ftmp = kmalloc( sizeof(struct ip_fw), GFP_ATOMIC );
  656. if ( ftmp == NULL )
  657. {
  658. #ifdef DEBUG_IP_FIREWALL
  659. printk("ip_fw_ctl:  malloc said non");
  660. #endif
  661. return( ENOMEM );
  662. }
  663. memcpy(ftmp, frwl, len);
  664. /*
  665.  * Allow the more recent "minimise cost" flag to be
  666.  * set. [Rob van Nieuwkerk]
  667.  */
  668. ftmp->fw_tosand |= 0x01;
  669. ftmp->fw_tosxor &= 0xFE;
  670. ftmp->fw_pcnt=0L;
  671. ftmp->fw_bcnt=0L;
  672. ftmp->fw_next = NULL;
  673. cli();
  674. if ((ftmp->fw_vianame)[0]) {
  675. if (!(ftmp->fw_viadev = dev_get_by_name(ftmp->fw_vianame)))
  676. ftmp->fw_viadev = (struct net_device *) -1;
  677. } else
  678. ftmp->fw_viadev = NULL;
  679. chtmp_prev=NULL;
  680. for (chtmp=*chainptr;chtmp!=NULL;chtmp=chtmp->fw_next)
  681. chtmp_prev=chtmp;
  682. if (chtmp_prev)
  683. chtmp_prev->fw_next=ftmp;
  684. else
  685.          *chainptr=ftmp;
  686. restore_flags(flags);
  687. MOD_INC_USE_COUNT;
  688. return(0);
  689. }
  690. static int del_from_chain(struct ip_fw *volatile*chainptr, struct ip_fw *frwl)
  691. {
  692. struct ip_fw  *ftmp,*ltmp;
  693. unsigned short tport1,tport2,tmpnum;
  694. char matches,was_found;
  695. unsigned long  flags;
  696. save_flags(flags);
  697. cli();
  698. ftmp=*chainptr;
  699. if ( ftmp == NULL )
  700. {
  701. #ifdef DEBUG_IP_FIREWALL
  702. printk("ip_fw_ctl:  chain is emptyn");
  703. #endif
  704. restore_flags(flags);
  705. return( EINVAL );
  706. }
  707. ltmp=NULL;
  708. was_found=0;
  709. while( !was_found && ftmp != NULL )
  710. {
  711. matches=1;
  712. if (ftmp->fw_src.s_addr!=frwl->fw_src.s_addr
  713.      ||  ftmp->fw_dst.s_addr!=frwl->fw_dst.s_addr
  714.      ||  ftmp->fw_smsk.s_addr!=frwl->fw_smsk.s_addr
  715.      ||  ftmp->fw_dmsk.s_addr!=frwl->fw_dmsk.s_addr
  716.      ||  ftmp->fw_via.s_addr!=frwl->fw_via.s_addr
  717.      ||  ftmp->fw_flg!=frwl->fw_flg)
  718.          matches=0;
  719. tport1=ftmp->fw_nsp+ftmp->fw_ndp;
  720. tport2=frwl->fw_nsp+frwl->fw_ndp;
  721. if (tport1!=tport2)
  722.         matches=0;
  723. else if (tport1!=0)
  724. {
  725. for (tmpnum=0;tmpnum < tport1 && tmpnum < IP_FW_MAX_PORTS;tmpnum++)
  726.          if (ftmp->fw_pts[tmpnum]!=frwl->fw_pts[tmpnum])
  727. matches=0;
  728. }
  729. if (strncmp(ftmp->fw_vianame, frwl->fw_vianame, IFNAMSIZ))
  730.         matches=0;
  731. if(matches)
  732. {
  733. was_found=1;
  734. if (ltmp)
  735. {
  736. ltmp->fw_next=ftmp->fw_next;
  737. kfree(ftmp);
  738. ftmp=ltmp->fw_next;
  739.          }
  740.        else
  741.        {
  742.        *chainptr=ftmp->fw_next;
  743.   kfree(ftmp);
  744. ftmp=*chainptr;
  745. }
  746. }
  747. else
  748. {
  749. ltmp = ftmp;
  750. ftmp = ftmp->fw_next;
  751.  }
  752. }
  753. restore_flags(flags);
  754. if (was_found) {
  755. MOD_DEC_USE_COUNT;
  756. return 0;
  757. } else
  758. return(EINVAL);
  759. }
  760. #endif  /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */
  761. struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len)
  762. {
  763. if ( len != sizeof(struct ip_fw) )
  764. {
  765. #ifdef DEBUG_IP_FIREWALL
  766. printk("ip_fw_ctl: len=%d, want %dn",len, sizeof(struct ip_fw));
  767. #endif
  768. return(NULL);
  769. }
  770. if ( (frwl->fw_flg & ~IP_FW_F_MASK) != 0 )
  771. {
  772. #ifdef DEBUG_IP_FIREWALL
  773. printk("ip_fw_ctl: undefined flag bits set (flags=%x)n",
  774. frwl->fw_flg);
  775. #endif
  776. return(NULL);
  777. }
  778. #ifndef CONFIG_IP_TRANSPARENT_PROXY
  779. if (frwl->fw_flg & IP_FW_F_REDIR) {
  780. #ifdef DEBUG_IP_FIREWALL
  781. printk("ip_fw_ctl: unsupported flag IP_FW_F_REDIRn");
  782. #endif
  783. return(NULL);
  784. }
  785. #endif
  786. #ifndef CONFIG_IP_MASQUERADE
  787. if (frwl->fw_flg & IP_FW_F_MASQ) {
  788. #ifdef DEBUG_IP_FIREWALL
  789. printk("ip_fw_ctl: unsupported flag IP_FW_F_MASQn");
  790. #endif
  791. return(NULL);
  792. }
  793. #endif
  794. if ( (frwl->fw_flg & IP_FW_F_SRNG) && frwl->fw_nsp < 2 )
  795. {
  796. #ifdef DEBUG_IP_FIREWALL
  797. printk("ip_fw_ctl: src range set but fw_nsp=%dn",
  798. frwl->fw_nsp);
  799. #endif
  800. return(NULL);
  801. }
  802. if ( (frwl->fw_flg & IP_FW_F_DRNG) && frwl->fw_ndp < 2 )
  803. {
  804. #ifdef DEBUG_IP_FIREWALL
  805. printk("ip_fw_ctl: dst range set but fw_ndp=%dn",
  806. frwl->fw_ndp);
  807. #endif
  808. return(NULL);
  809. }
  810. if ( frwl->fw_nsp + frwl->fw_ndp > (frwl->fw_flg & IP_FW_F_REDIR ? IP_FW_MAX_PORTS - 1 : IP_FW_MAX_PORTS) )
  811. {
  812. #ifdef DEBUG_IP_FIREWALL
  813. printk("ip_fw_ctl: too many ports (%d+%d)n",
  814. frwl->fw_nsp,frwl->fw_ndp);
  815. #endif
  816. return(NULL);
  817. }
  818. return frwl;
  819. }
  820. #ifdef CONFIG_IP_ACCT
  821. int ip_acct_ctl(int stage, void *m, int len)
  822. {
  823. if ( stage == IP_ACCT_FLUSH )
  824. {
  825. free_fw_chain(&ip_acct_chain);
  826. return(0);
  827. }
  828. if ( stage == IP_ACCT_ZERO )
  829. {
  830. zero_fw_chain(ip_acct_chain);
  831. return(0);
  832. }
  833. if ( stage == IP_ACCT_INSERT || stage == IP_ACCT_APPEND ||
  834.    stage == IP_ACCT_DELETE )
  835. {
  836. struct ip_fw *frwl;
  837. if (!(frwl=check_ipfw_struct(m,len)))
  838. return (EINVAL);
  839. switch (stage)
  840. {
  841. case IP_ACCT_INSERT:
  842. return( insert_in_chain(&ip_acct_chain,frwl,len));
  843. case IP_ACCT_APPEND:
  844. return( append_to_chain(&ip_acct_chain,frwl,len));
  845.      case IP_ACCT_DELETE:
  846. return( del_from_chain(&ip_acct_chain,frwl));
  847. default:
  848. /*
  849.    * Should be panic but... (Why ??? - AC)
  850.  */
  851. #ifdef DEBUG_IP_FIREWALL
  852. printk("ip_acct_ctl:  unknown request %dn",stage);
  853. #endif
  854. return(EINVAL);
  855. }
  856. }
  857. #ifdef DEBUG_IP_FIREWALL
  858. printk("ip_acct_ctl:  unknown request %dn",stage);
  859. #endif
  860. return(EINVAL);
  861. }
  862. #endif
  863. #ifdef CONFIG_IP_FIREWALL
  864. int ip_fw_ctl(int stage, void *m, int len)
  865. {
  866. int cmd, fwtype;
  867. cmd = stage & IP_FW_COMMAND;
  868. fwtype = (stage & IP_FW_TYPE) >> IP_FW_SHIFT;
  869. if ( cmd == IP_FW_FLUSH )
  870. {
  871. free_fw_chain(chains[fwtype]);
  872. return(0);
  873. }
  874. if ( cmd == IP_FW_ZERO )
  875. {
  876. zero_fw_chain(*chains[fwtype]);
  877. return(0);
  878. }
  879. if ( cmd == IP_FW_POLICY )
  880. {
  881. int *tmp_policy_ptr;
  882. tmp_policy_ptr=(int *)m;
  883. *policies[fwtype] = *tmp_policy_ptr;
  884. return 0;
  885. }
  886. if ( cmd == IP_FW_CHECK )
  887. {
  888. struct net_device *viadev;
  889. struct ip_fwpkt *ipfwp;
  890. struct iphdr *ip;
  891. if ( len != sizeof(struct ip_fwpkt) )
  892. {
  893. #ifdef DEBUG_IP_FIREWALL
  894. printk("ip_fw_ctl: length=%d, expected %dn",
  895. len, sizeof(struct ip_fwpkt));
  896. #endif
  897. return( EINVAL );
  898. }
  899.   ipfwp = (struct ip_fwpkt *)m;
  900.   ip = &(ipfwp->fwp_iph);
  901. if ( !(viadev = dev_get_by_name(ipfwp->fwp_vianame)) ) {
  902. #ifdef DEBUG_IP_FIREWALL
  903. printk("ip_fw_ctl: invalid device "%s"n", ipfwp->fwp_vianame);
  904. #endif
  905. return(EINVAL);
  906. } else if ( ip->ihl != sizeof(struct iphdr) / sizeof(int)) {
  907. #ifdef DEBUG_IP_FIREWALL
  908. printk("ip_fw_ctl: ip->ihl=%d, want %dn",ip->ihl,
  909. sizeof(struct iphdr)/sizeof(int));
  910. #endif
  911. return(EINVAL);
  912. }
  913. switch (ip_fw_chk(ip, viadev, NULL, *chains[fwtype],
  914. *policies[fwtype], IP_FW_MODE_CHK))
  915. {
  916. case FW_ACCEPT:
  917. return(0);
  918.      case FW_REDIRECT:
  919. return(ECONNABORTED);
  920.      case FW_MASQUERADE:
  921. return(ECONNRESET);
  922.      case FW_REJECT:
  923. return(ECONNREFUSED);
  924. default: /* FW_BLOCK */
  925. return(ETIMEDOUT);
  926. }
  927. }
  928. if ( cmd == IP_FW_MASQ_TIMEOUTS )
  929. return ip_fw_masq_timeouts(m, len);
  930. /*
  931.  * Here we really working hard-adding new elements
  932.  * to blocking/forwarding chains or deleting 'em
  933.  */
  934. if ( cmd == IP_FW_INSERT || cmd == IP_FW_APPEND || cmd == IP_FW_DELETE )
  935. {
  936. struct ip_fw *frwl;
  937. int fwtype;
  938. frwl=check_ipfw_struct(m,len);
  939. if (frwl==NULL)
  940. return (EINVAL);
  941. fwtype = (stage & IP_FW_TYPE) >> IP_FW_SHIFT;
  942. switch (cmd)
  943. {
  944. case IP_FW_INSERT:
  945. return(insert_in_chain(chains[fwtype],frwl,len));
  946. case IP_FW_APPEND:
  947. return(append_to_chain(chains[fwtype],frwl,len));
  948. case IP_FW_DELETE:
  949. return(del_from_chain(chains[fwtype],frwl));
  950. default:
  951. /*
  952.    * Should be panic but... (Why are BSD people panic obsessed ??)
  953.  */
  954. #ifdef DEBUG_IP_FIREWALL
  955. printk("ip_fw_ctl:  unknown request %dn",stage);
  956. #endif
  957. return(EINVAL);
  958. }
  959. }
  960. #ifdef DEBUG_IP_FIREWALL
  961. printk("ip_fw_ctl:  unknown request %dn",stage);
  962. #endif
  963. return(ENOPROTOOPT);
  964. }
  965. #endif /* CONFIG_IP_FIREWALL */
  966. #if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT)
  967. static int ip_chain_procinfo(int stage, char *buffer, char **start,
  968.      off_t offset, int length, int reset)
  969. {
  970. off_t pos=0, begin=0;
  971. struct ip_fw *i;
  972. unsigned long flags;
  973. int len, p;
  974. int last_len = 0;
  975. switch(stage)
  976. {
  977. #ifdef CONFIG_IP_FIREWALL
  978. case IP_FW_IN:
  979. i = ip_fw_in_chain;
  980. len=sprintf(buffer, "IP firewall input rules, default %dn",
  981. ip_fw_in_policy);
  982. break;
  983. case IP_FW_OUT:
  984. i = ip_fw_out_chain;
  985. len=sprintf(buffer, "IP firewall output rules, default %dn",
  986. ip_fw_out_policy);
  987. break;
  988. case IP_FW_FWD:
  989. i = ip_fw_fwd_chain;
  990. len=sprintf(buffer, "IP firewall forward rules, default %dn",
  991. ip_fw_fwd_policy);
  992. break;
  993. #endif
  994. #ifdef CONFIG_IP_ACCT
  995. case IP_FW_ACCT:
  996. i = ip_acct_chain;
  997. len=sprintf(buffer,"IP accounting rulesn");
  998. break;
  999. #endif
  1000. default:
  1001. /* this should never be reached, but safety first... */
  1002. i = NULL;
  1003. len=0;
  1004. break;
  1005. }
  1006. save_flags(flags);
  1007. cli();
  1008. while(i!=NULL)
  1009. {
  1010. len+=sprintf(buffer+len,"%08X/%08X->%08X/%08X %.16s %08X %X ",
  1011. ntohl(i->fw_src.s_addr),ntohl(i->fw_smsk.s_addr),
  1012. ntohl(i->fw_dst.s_addr),ntohl(i->fw_dmsk.s_addr),
  1013. (i->fw_vianame)[0] ? i->fw_vianame : "-",
  1014. ntohl(i->fw_via.s_addr), i->fw_flg);
  1015. /* 10 is enough for a 32 bit box but the counters are 64bit on
  1016.    the Alpha and Ultrapenguin */
  1017. len+=sprintf(buffer+len,"%u %u %-20lu %-20lu",
  1018. i->fw_nsp,i->fw_ndp, i->fw_pcnt,i->fw_bcnt);
  1019. for (p = 0; p < IP_FW_MAX_PORTS; p++)
  1020. len+=sprintf(buffer+len, " %u", i->fw_pts[p]);
  1021. len+=sprintf(buffer+len, " A%02X X%02X", i->fw_tosand, i->fw_tosxor);
  1022. buffer[len++]='n';
  1023. buffer[len]='';
  1024. pos=begin+len;
  1025. if(pos<offset)
  1026. {
  1027. len=0;
  1028. begin=pos;
  1029. }
  1030. else if(pos>offset+length)
  1031. {
  1032. len = last_len;
  1033. break;
  1034. }
  1035. else if(reset)
  1036. {
  1037. /* This needs to be done at this specific place! */
  1038. i->fw_pcnt=0L;
  1039. i->fw_bcnt=0L;
  1040. }
  1041. last_len = len;
  1042. i=i->fw_next;
  1043. }
  1044. restore_flags(flags);
  1045. *start=buffer+(offset-begin);
  1046. len-=(offset-begin);
  1047. if(len>length)
  1048. len=length;
  1049. return len;
  1050. }
  1051. #endif
  1052. #ifdef CONFIG_IP_ACCT
  1053. static int ip_acct_procinfo(char *buffer, char **start, off_t offset,
  1054.     int length
  1055. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,29)
  1056.     , int reset
  1057. #endif
  1058. )
  1059. {
  1060. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,29)
  1061. /* FIXME: No more `atomic' read and reset.  Wonderful 8-( --RR */
  1062. int reset = 0;
  1063. #endif
  1064. return ip_chain_procinfo(IP_FW_ACCT, buffer,start, offset,length,
  1065.  reset);
  1066. }
  1067. #endif
  1068. #ifdef CONFIG_IP_FIREWALL
  1069. static int ip_fw_in_procinfo(char *buffer, char **start, off_t offset,
  1070.       int length
  1071. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,29)
  1072.      , int reset
  1073. #endif
  1074. )
  1075. {
  1076. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,29)
  1077. /* FIXME: No more `atomic' read and reset.  Wonderful 8-( --RR */
  1078. int reset = 0;
  1079. #endif
  1080. return ip_chain_procinfo(IP_FW_IN, buffer,start,offset,length,
  1081.  reset);
  1082. }
  1083. static int ip_fw_out_procinfo(char *buffer, char **start, off_t offset,
  1084.       int length
  1085. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,29)
  1086.     , int reset
  1087. #endif
  1088. )
  1089. {
  1090. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,29)
  1091. /* FIXME: No more `atomic' read and reset.  Wonderful 8-( --RR */
  1092. int reset = 0;
  1093. #endif
  1094. return ip_chain_procinfo(IP_FW_OUT, buffer,start,offset,length,
  1095.  reset);
  1096. }
  1097. static int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset,
  1098.       int length
  1099. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,29)
  1100.     , int reset
  1101. #endif
  1102. )
  1103. {
  1104. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,29)
  1105. /* FIXME: No more `atomic' read and reset.  Wonderful 8-( --RR */
  1106. int reset = 0;
  1107. #endif
  1108. return ip_chain_procinfo(IP_FW_FWD, buffer,start,offset,length,
  1109.  reset);
  1110. }
  1111. #endif
  1112. #ifdef CONFIG_IP_FIREWALL
  1113. /*
  1114.  * Interface to the generic firewall chains.
  1115.  */
  1116. int ipfw_input_check(struct firewall_ops *this, int pf,
  1117.      struct net_device *dev, void *phdr, void *arg,
  1118.      struct sk_buff **pskb)
  1119. {
  1120. return ip_fw_chk(phdr, dev, arg, ip_fw_in_chain, ip_fw_in_policy,
  1121.  IP_FW_MODE_FW);
  1122. }
  1123. int ipfw_output_check(struct firewall_ops *this, int pf,
  1124.       struct net_device *dev, void *phdr, void *arg,
  1125.       struct sk_buff **pskb)
  1126. {
  1127. return ip_fw_chk(phdr, dev, arg, ip_fw_out_chain, ip_fw_out_policy,
  1128.  IP_FW_MODE_FW);
  1129. }
  1130. int ipfw_forward_check(struct firewall_ops *this, int pf,
  1131.        struct net_device *dev, void *phdr, void *arg,
  1132.        struct sk_buff **pskb)
  1133. {
  1134. return ip_fw_chk(phdr, dev, arg, ip_fw_fwd_chain, ip_fw_fwd_policy,
  1135.  IP_FW_MODE_FW);
  1136. }
  1137. #ifdef CONFIG_IP_ACCT
  1138. int ipfw_acct_in(struct firewall_ops *this, int pf, struct net_device *dev,
  1139.  void *phdr, void *arg, struct sk_buff **pskb)
  1140. {
  1141. return ip_fw_chk(phdr,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_IN);
  1142. }
  1143. int ipfw_acct_out(struct firewall_ops *this, int pf, struct net_device *dev,
  1144.   void *phdr, void *arg, struct sk_buff **pskb)
  1145. {
  1146. return ip_fw_chk(phdr,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_OUT);
  1147. }
  1148. #endif
  1149. struct firewall_ops ipfw_ops=
  1150. {
  1151. NULL,
  1152. ipfw_forward_check,
  1153. ipfw_input_check,
  1154. ipfw_output_check,
  1155. #ifdef CONFIG_IP_ACCT
  1156. ipfw_acct_in,
  1157. ipfw_acct_out
  1158. #else
  1159. NULL,
  1160. NULL
  1161. #endif
  1162. };
  1163. #endif
  1164. #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
  1165. int ipfw_device_event(struct notifier_block *this, unsigned long event, void *ptr)
  1166. {
  1167. struct net_device *dev=ptr;
  1168. char *devname = dev->name;
  1169. unsigned long flags;
  1170. struct ip_fw *fw;
  1171. int chn;
  1172. save_flags(flags);
  1173. cli();
  1174. if (event == NETDEV_UP) {
  1175. for (chn = 0; chn < IP_FW_CHAINS; chn++)
  1176. for (fw = *chains[chn]; fw; fw = fw->fw_next)
  1177. if ((fw->fw_vianame)[0] && !strncmp(devname,
  1178. fw->fw_vianame, IFNAMSIZ))
  1179. fw->fw_viadev = dev;
  1180. } else if (event == NETDEV_DOWN) {
  1181. for (chn = 0; chn < IP_FW_CHAINS; chn++)
  1182. for (fw = *chains[chn]; fw; fw = fw->fw_next)
  1183. /* we could compare just the pointers ... */
  1184. if ((fw->fw_vianame)[0] && !strncmp(devname,
  1185. fw->fw_vianame, IFNAMSIZ))
  1186. fw->fw_viadev = (struct net_device*)-1;
  1187. }
  1188. restore_flags(flags);
  1189. return NOTIFY_DONE;
  1190. }
  1191. static struct notifier_block ipfw_dev_notifier={
  1192. ipfw_device_event,
  1193. NULL,
  1194. 0
  1195. };
  1196. #endif
  1197. int ipfw_init_or_cleanup(int init)
  1198. {
  1199. int ret = 0;
  1200. if (!init)
  1201. goto cleanup;
  1202. ret = register_firewall(PF_INET, &ipfw_ops);
  1203. if (ret < 0)
  1204. goto cleanup_nothing;
  1205. #ifdef CONFIG_IP_ACCT
  1206. proc_net_create("ip_acct", S_IFREG | S_IRUGO | S_IWUSR, ip_acct_procinfo);
  1207. #endif
  1208. proc_net_create("ip_input", S_IFREG | S_IRUGO | S_IWUSR, ip_fw_in_procinfo);
  1209. proc_net_create("ip_output", S_IFREG | S_IRUGO | S_IWUSR, ip_fw_out_procinfo);
  1210. proc_net_create("ip_forward", S_IFREG | S_IRUGO | S_IWUSR, ip_fw_fwd_procinfo);
  1211. /* Register for device up/down reports */
  1212. register_netdevice_notifier(&ipfw_dev_notifier);
  1213. #ifdef CONFIG_IP_FIREWALL_NETLINK
  1214. ipfwsk = netlink_kernel_create(NETLINK_FIREWALL, NULL);
  1215. #endif
  1216. return ret;
  1217.  cleanup:
  1218. #ifdef CONFIG_IP_FIREWALL_NETLINK
  1219. sock_release(ipfwsk->socket);
  1220. #endif
  1221. unregister_netdevice_notifier(&ipfw_dev_notifier);
  1222. #ifdef CONFIG_IP_ACCT
  1223. proc_net_remove("ip_acct");
  1224. #endif
  1225. proc_net_remove("ip_input");
  1226. proc_net_remove("ip_output");
  1227. proc_net_remove("ip_forward");
  1228. free_fw_chain(chains[IP_FW_FWD]);
  1229. free_fw_chain(chains[IP_FW_IN]);
  1230. free_fw_chain(chains[IP_FW_OUT]);
  1231. free_fw_chain(chains[IP_FW_ACCT]);
  1232. unregister_firewall(PF_INET, &ipfw_ops);
  1233.  cleanup_nothing:
  1234. return ret;
  1235. }