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
This commit is contained in:
Poul-Henning Kamp 1996-02-24 13:38:28 +00:00
parent 5b0c234e20
commit 09bb5f7589
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=14232
5 changed files with 121 additions and 48 deletions

View File

@ -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));

View File

@ -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 <sys/exec.h>
#include <sys/sysent.h>
#include <sys/lkm.h>
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

View File

@ -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.

View File

@ -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 <sys/param.h>
@ -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)

View File

@ -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 <sys/param.h>
@ -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: