From 45a7f29691072258573e111c1034432e37e944f2 Mon Sep 17 00:00:00 2001 From: phk Date: Sat, 24 Feb 1996 13:38:28 +0000 Subject: [PATCH] Make getsockopt() capable of handling more than one mbuf worth of data. Use this to read rules out of ipfw. Add the lkm code to ipfw.c --- sys/kern/uipc_syscalls.c | 19 ++++--- sys/netinet/ip_fw.c | 109 +++++++++++++++++++++++++++++++++------ sys/netinet/ip_fw.h | 14 ++--- sys/netinet/ip_input.c | 6 +-- sys/netinet/raw_ip.c | 21 ++++---- 5 files changed, 121 insertions(+), 48 deletions(-) diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index f994a40f5564..ac92bf2f1650 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 - * $Id: uipc_syscalls.c,v 1.13 1996/01/28 23:41:40 dyson Exp $ + * $Id: uipc_syscalls.c,v 1.14 1996/02/13 18:16:21 wollman Exp $ */ #include "opt_ktrace.h" @@ -991,8 +991,8 @@ getsockopt(p, uap, retval) int *retval; { struct file *fp; - struct mbuf *m = NULL; - int valsize, error; + struct mbuf *m = NULL, *m0; + int op, i, valsize, error; error = getsock(p->p_fd, uap->s, &fp); if (error) @@ -1006,9 +1006,16 @@ getsockopt(p, uap, retval) valsize = 0; if ((error = sogetopt((struct socket *)fp->f_data, uap->level, uap->name, &m)) == 0 && uap->val && valsize && m != NULL) { - if (valsize > m->m_len) - valsize = m->m_len; - error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize); + op = 0; + while (m && !error && op < valsize) { + i = min(m->m_len, (valsize - op)); + error = copyout(mtod(m, caddr_t), uap->val, (u_int)i); + op += i; + uap->val += i; + m0 = m; + MFREE(m0,m); + } + valsize = op; if (error == 0) error = copyout((caddr_t)&valsize, (caddr_t)uap->avalsize, sizeof (valsize)); diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c index 8a23930c83f8..49b561e922f4 100644 --- a/sys/netinet/ip_fw.c +++ b/sys/netinet/ip_fw.c @@ -11,7 +11,7 @@ * * This software is provided ``AS IS'' without any warranties of any kind. * - * $Id: ip_fw.c,v 1.30 1996/02/23 20:11:37 phk Exp $ + * $Id: ip_fw.c,v 1.31 1996/02/24 00:17:32 phk Exp $ */ /* @@ -42,7 +42,6 @@ static int fw_verbose = 1; static int fw_verbose = 0; #endif -u_short ip_fw_policy = IP_FW_P_DENY; LIST_HEAD (ip_fw_head, ip_fw_chain) ip_fw_chain; @@ -71,6 +70,9 @@ static int port_match __P((u_short *portptr, int nports, u_short port, static int tcpflg_match __P((struct tcphdr *tcp, struct ip_fw *f)); static void ipfw_report __P((char *txt, int rule, struct ip *ip)); +static int (*old_chk_ptr)(struct mbuf *, struct ip *,struct ifnet *, int dir); +static int (*old_ctl_ptr)(int,struct mbuf **); + /* * Returns 1 if the port is matched by the vector, 0 otherwise */ @@ -140,7 +142,7 @@ ipopts_match(ip, f) else { optlen = cp[IPOPT_OLEN]; if (optlen <= 0 || optlen > cnt) { - goto bad; + return 0; /*XXX*/ } } switch (opt) { @@ -174,12 +176,6 @@ ipopts_match(ip, f) return 1; else return 0; -bad: - if (ip_fw_policy & IP_FW_P_MBIPO) - return 1; - else - return 0; - } static void @@ -570,10 +566,26 @@ check_ipfw_struct(m) } int -ip_fw_ctl(stage, m) +ip_fw_ctl(stage, mm) int stage; - struct mbuf *m; + struct mbuf **mm; { + int error; + struct mbuf *m; + + if (stage == IP_FW_GET) { + struct ip_fw_chain *fcp = ip_fw_chain.lh_first; + *mm = m = m_get(M_WAIT, MT_SOOPTS); + for (; fcp; fcp = fcp->chain.le_next) { + memcpy(m->m_data, fcp->rule, sizeof *(fcp->rule)); + m->m_len = sizeof *(fcp->rule); + m->m_next = m_get(M_WAIT, MT_SOOPTS); + m = m->m_next; + m->m_len = 0; + } + return (0); + } + m = *mm; if (stage == IP_FW_FLUSH) { while (ip_fw_chain.lh_first != NULL && ip_fw_chain.lh_first->rule->fw_number != (u_short)-1) { @@ -582,12 +594,14 @@ ip_fw_ctl(stage, m) free(fcp->rule, M_IPFW); free(fcp, M_IPFW); } + if (m) (void)m_free(m); return (0); } if (stage == IP_FW_ZERO) { struct ip_fw_chain *fcp; for (fcp = ip_fw_chain.lh_first; fcp; fcp = fcp->chain.le_next) fcp->rule->fw_bcnt = fcp->rule->fw_pcnt = 0; + if (m) (void)m_free(m); return (0); } if (m == NULL) { @@ -598,15 +612,20 @@ ip_fw_ctl(stage, m) if (stage == IP_FW_ADD || stage == IP_FW_DEL) { struct ip_fw *frwl = check_ipfw_struct(m); - if (!frwl) + if (!frwl) { + if (m) (void)m_free(m); return (EINVAL); + } if (stage == IP_FW_ADD) - return (add_entry(&ip_fw_chain, frwl)); + error = add_entry(&ip_fw_chain, frwl); else - return (del_entry(&ip_fw_chain, frwl)); + error = del_entry(&ip_fw_chain, frwl); + if (m) (void)m_free(m); + return error; } dprintf(("ip_fw_ctl: unknown request %d\n", stage)); + if (m) (void)m_free(m); return (EINVAL); } @@ -615,15 +634,71 @@ ip_fw_init(void) { struct ip_fw deny; - ip_fw_chk_ptr=&ip_fw_chk; - ip_fw_ctl_ptr=&ip_fw_ctl; + ip_fw_chk_ptr = ip_fw_chk; + ip_fw_ctl_ptr = ip_fw_ctl; LIST_INIT(&ip_fw_chain); bzero(&deny, sizeof deny); deny.fw_flg = IP_FW_F_ALL; deny.fw_number = (u_short)-1; - add_entry(&ip_fw_chain, &deny); printf("IP firewall initialized\n"); } + +#ifdef ACTUALLY_LKM_NOT_KERNEL + +#include +#include +#include + +MOD_MISC(ipfw); + +static int +ipfw_load(struct lkm_table *lkmtp, int cmd) +{ + int s=splnet(); + struct ip_fw deny; + + old_chk_ptr = ip_fw_chk_ptr; + old_ctl_ptr = ip_fw_ctl_ptr; + ip_fw_chk_ptr = ip_fw_chk; + ip_fw_ctl_ptr = ip_fw_ctl; + + LIST_INIT(&ip_fw_chain); + bzero(&deny, sizeof deny); + deny.fw_flg = IP_FW_F_ALL; + deny.fw_number = (u_short)-1; + add_entry(&ip_fw_chain, &deny); + + splx(s); + printf("IP firewall loaded\n"); + return 0; +} + +static int +ipfw_unload(struct lkm_table *lkmtp, int cmd) +{ + int s=splnet(); + + ip_fw_chk_ptr = old_chk_ptr; + ip_fw_ctl_ptr = old_ctl_ptr; + + while (ip_fw_chain.lh_first != NULL) { + struct ip_fw_chain *fcp = ip_fw_chain.lh_first; + LIST_REMOVE(ip_fw_chain.lh_first, chain); + free(fcp->rule, M_IPFW); + free(fcp, M_IPFW); + } + + splx(s); + printf("IP firewall unloaded\n"); + return 0; +} + +int +ipfw_mod(struct lkm_table *lkmtp, int cmd, int ver) +{ + DISPATCH(lkmtp, cmd, ver, ipfw_load, ipfw_unload, lkm_nullcmd); +} +#endif diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index f39688ca281a..9f6ac09b6da4 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -11,7 +11,7 @@ * * This software is provided ``AS IS'' without any warranties of any kind. * - * $Id: ip_fw.h,v 1.15 1996/02/23 15:47:52 phk Exp $ + * $Id: ip_fw.h,v 1.16 1996/02/24 00:17:33 phk Exp $ */ /* @@ -115,15 +115,7 @@ struct ip_fw_chain { #define IP_FW_DEL (IP_FW_BASE_CTL+1) #define IP_FW_FLUSH (IP_FW_BASE_CTL+2) #define IP_FW_ZERO (IP_FW_BASE_CTL+3) - -/* - * Policy flags... - */ -#define IP_FW_P_DENY 0x01 -#define IP_FW_P_ICMP 0x02 -#define IP_FW_P_MBIPO 0x04 -#define IP_FW_P_MASK 0x07 - +#define IP_FW_GET (IP_FW_BASE_CTL+4) /* * Main firewall chains definitions and global var's definitions. @@ -134,7 +126,7 @@ struct ip_fw_chain { * Function pointers. */ extern int (*ip_fw_chk_ptr)(struct mbuf *, struct ip *,struct ifnet *, int dir); -extern int (*ip_fw_ctl_ptr)(int,struct mbuf *); +extern int (*ip_fw_ctl_ptr)(int,struct mbuf **); /* * Function definitions. diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 15d053a482f0..04de9cb4c07f 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 - * $Id: ip_input.c,v 1.36 1996/02/23 15:47:53 phk Exp $ + * $Id: ip_input.c,v 1.37 1996/02/24 00:17:34 phk Exp $ */ #include @@ -121,7 +121,7 @@ dummy_ip_fw_chk(m, ip, rif, dir) int (*ip_fw_chk_ptr)(struct mbuf *, struct ip *, struct ifnet *, int dir) = dummy_ip_fw_chk; -int (*ip_fw_ctl_ptr)(int, struct mbuf *); +int (*ip_fw_ctl_ptr)(int, struct mbuf **); /* * We need to save the IP options in case a protocol wants to respond @@ -190,7 +190,7 @@ ip_input(struct mbuf *m) register struct ip *ip; register struct ipq *fp; register struct in_ifaddr *ia; - int hlen, s; + int hlen; #ifdef DIAGNOSTIC if ((m->m_flags & M_PKTHDR) == 0) diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 4d9916d0c737..e8076b6838ee 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)raw_ip.c 8.7 (Berkeley) 5/15/95 - * $Id: raw_ip.c,v 1.25 1995/12/09 20:43:53 phk Exp $ + * $Id: raw_ip.c,v 1.26 1996/02/23 15:47:58 phk Exp $ */ #include @@ -218,23 +218,22 @@ rip_ctloutput(op, so, level, optname, m) } return (error); + case IP_FW_GET: + if (ip_fw_ctl_ptr==NULL || op == PRCO_SETOPT) { + if (*m) (void)m_free(*m); + return(EINVAL); + } + return (*ip_fw_ctl_ptr)(optname, m); case IP_FW_ADD: case IP_FW_DEL: case IP_FW_FLUSH: case IP_FW_ZERO: - if (ip_fw_ctl_ptr==NULL) { - if (*m) - (void)m_free(*m); + if (ip_fw_ctl_ptr==NULL || op != PRCO_SETOPT) { + if (*m) (void)m_free(*m); return(EINVAL); } - if (op == PRCO_SETOPT) { - error=(*ip_fw_ctl_ptr)(optname, *m); - if (*m) - (void)m_free(*m); - } - else - error=EINVAL; + return (*ip_fw_ctl_ptr)(optname, m); return(error); case IP_RSVP_ON: