IGMP/ICMP/IPIP/IDP/RSVP/IPIP/IPPROTO_RAW KERNEL CHECKER.
88d150b0fb1f12572bd32f4c4c131012166c8ebc26ac873c1c57d35c641e1113
/*
* IGMP/ICMP/IPIP/IDP/RSVP/IPIP/IPPROTO_RAW KERNEL CHECKER
*
* These protocols have the same pr_usrreqs... This is a kld to monitor
* their packets via FreeBSD kernel.
*
* idea & code by pIGpEN [pigpen@s0ftpj.org, deadhead@sikurezza.org ]
*
* Tested on FreeBSD CURRENT 4.0
*
* s0ftpr0ject - digital security for y2k
* www.s0ftpj.org
*
* sikurezza.org - italian security mailing list
* www.sikurezza.org
*
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/proc.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <vm/vm_zone.h>
#include <net/if.h>
#include <net/route.h>
#define _IP_VHL
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/in_pcb.h>
#include <netinet/in_var.h>
#include <netinet/ip_var.h>
#include <netinet/ip_mroute.h>
#define print_ip(a) printf("%d.%d.%d.%d\n", \
(int)(ntohl(a) >>24) & 0xFF, \
(int)(ntohl(a) >>16) & 0xFF, \
(int)(ntohl(a) >> 8) & 0xFF, \
(int)(ntohl(a)) & 0xFF);
static int rip_new_send __P((struct socket *, int, struct mbuf *,
struct sockaddr *, struct mbuf *,
struct proc *));
static int (*old_rip_send) __P((struct socket *, int, struct mbuf *,
struct sockaddr *, struct mbuf *,
struct proc *));
static int rip_my_output __P((register struct mbuf *,
struct socket *, u_long));
static int s_load __P((struct module *, int, void *));
/* il controllo si poteva fare direttamente su questa funzione.... non l'ho
fatto perche' avevo gia' messo la mia rip_my_output nel sorgente :) */
static int
rip_new_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
struct mbuf *control, struct proc *p)
{
struct inpcb *inp = sotoinpcb(so);
register u_long dst;
if (so->so_state & SS_ISCONNECTED) {
if (nam) {
m_freem(m);
return EISCONN;
}
dst = inp->inp_faddr.s_addr;
} else {
if (nam == NULL) {
m_freem(m);
return ENOTCONN;
}
dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr;
}
return rip_my_output(m, so, dst);
}
static int
rip_my_output(m, so, dst)
register struct mbuf *m;
struct socket *so;
u_long dst;
{
register struct ip *ip;
register struct inpcb *inp = sotoinpcb(so);
int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
switch(inp->inp_ip_p) {
case IPPROTO_RAW: printf("RAW");
break;
case IPPROTO_ICMP: printf("ICMP");
break;
case IPPROTO_IGMP: printf("IGMP");
break;
case IPPROTO_RSVP: printf("RSVP");
break;
case IPPROTO_IPIP: printf("IPIP");
break;
case IPPROTO_IDP: printf("IDP");
break;
default: printf("#%d", inp->inp_ip_p);
break;
}
printf(" -> "); print_ip(dst);
/*
* If the user handed us a complete IP packet, use it.
* Otherwise, allocate an mbuf for a header and fill it in.
*/
if ((inp->inp_flags & INP_HDRINCL) == 0) {
if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) {
m_freem(m);
return(EMSGSIZE);
}
M_PREPEND(m, sizeof(struct ip), M_WAIT);
ip = mtod(m, struct ip *);
ip->ip_tos = 0;
ip->ip_off = 0;
ip->ip_p = inp->inp_ip_p;
ip->ip_len = m->m_pkthdr.len;
ip->ip_src = inp->inp_laddr;
ip->ip_dst.s_addr = dst;
ip->ip_ttl = MAXTTL;
} else {
if (m->m_pkthdr.len > IP_MAXPACKET) {
m_freem(m);
return(EMSGSIZE);
}
ip = mtod(m, struct ip *);
/* don't allow both user specified and setsockopt options,
and don't allow packet length sizes that will crash */
if (((IP_VHL_HL(ip->ip_vhl) != (sizeof (*ip) >> 2))
&& inp->inp_options)
|| (ip->ip_len > m->m_pkthdr.len)
|| (ip->ip_len < (IP_VHL_HL(ip->ip_vhl) << 2))) {
m_freem(m);
return EINVAL;
}
if (ip->ip_id == 0)
ip->ip_id = htons(ip_id++);
/* XXX prevent ip_output from overwriting header fields */
flags |= IP_RAWOUTPUT;
ipstat.ips_rawout++;
}
return (ip_output(m, inp->inp_options, &inp->inp_route, flags,
inp->inp_moptions));
}
extern struct protosw inetsw[];
static int
s_load (struct module *module, int cmd, void *arg)
{
int s;
switch(cmd) {
case MOD_LOAD:
s=splnet();
old_rip_send = inetsw[ip_protox[IPPROTO_ICMP]].pr_usrreqs->pru_send;
inetsw[ip_protox[IPPROTO_ICMP]].pr_usrreqs->pru_send = rip_new_send;
splx(s);
break;
case MOD_UNLOAD:
s=splnet();
inetsw[ip_protox[IPPROTO_ICMP]].pr_usrreqs->pru_send = old_rip_send;
splx(s);
break;
}
return 0;
}
static moduledata_t s_mod_1 = {
"raww_mod",
s_load,
0
};
DECLARE_MODULE(raww_mod, s_mod_1, SI_SUB_PSEUDO, SI_ORDER_ANY);