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:
parent
dde0a4d2ee
commit
076edba777
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user