xref: /csrg-svn/sys/net/raw_cb.c (revision 17066)
1*17066Sbloom /*	raw_cb.c	6.2	84/08/29	*/
25635Sroot 
3*17066Sbloom #include "param.h"
4*17066Sbloom #include "systm.h"
5*17066Sbloom #include "mbuf.h"
6*17066Sbloom #include "socket.h"
7*17066Sbloom #include "socketvar.h"
8*17066Sbloom #include "errno.h"
910890Ssam 
10*17066Sbloom #include "if.h"
11*17066Sbloom #include "route.h"
12*17066Sbloom #include "raw_cb.h"
1312783Ssam #include "../netinet/in.h"
1412783Ssam #include "../netpup/pup.h"
155635Sroot 
1610890Ssam #include "../vax/mtpr.h"
1710890Ssam 
185635Sroot /*
195635Sroot  * Routines to manage the raw protocol control blocks.
205635Sroot  *
215635Sroot  * TODO:
225635Sroot  *	hash lookups by protocol family/protocol + address family
236339Ssam  *	take care of unique address problems per AF?
246045Swnj  *	redo address binding to allow wildcards
255635Sroot  */
265635Sroot 
275635Sroot /*
285635Sroot  * Allocate a control block and a nominal amount
295635Sroot  * of buffer space for the socket.
305635Sroot  */
318394Swnj raw_attach(so)
325635Sroot 	register struct socket *so;
335635Sroot {
345635Sroot 	struct mbuf *m;
355635Sroot 	register struct rawcb *rp;
365635Sroot 
379638Ssam 	m = m_getclr(M_DONTWAIT, MT_PCB);
385635Sroot 	if (m == 0)
395635Sroot 		return (ENOBUFS);
405635Sroot 	if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
415635Sroot 		goto bad;
425635Sroot 	if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
435635Sroot 		goto bad2;
445635Sroot 	rp = mtod(m, struct rawcb *);
455635Sroot 	rp->rcb_socket = so;
465635Sroot 	insque(rp, &rawcb);
475635Sroot 	so->so_pcb = (caddr_t)rp;
485635Sroot 	rp->rcb_pcb = 0;
495635Sroot 	return (0);
505635Sroot bad2:
515635Sroot 	sbrelease(&so->so_snd);
525635Sroot bad:
535635Sroot 	(void) m_free(m);
545635Sroot 	return (ENOBUFS);
555635Sroot }
565635Sroot 
575635Sroot /*
585635Sroot  * Detach the raw connection block and discard
595635Sroot  * socket resources.
605635Sroot  */
615635Sroot raw_detach(rp)
625635Sroot 	register struct rawcb *rp;
635635Sroot {
645635Sroot 	struct socket *so = rp->rcb_socket;
655635Sroot 
665635Sroot 	so->so_pcb = 0;
675635Sroot 	sofree(so);
685635Sroot 	remque(rp);
698975Sroot 	m_freem(dtom(rp));
705635Sroot }
715635Sroot 
725635Sroot /*
735635Sroot  * Disconnect and possibly release resources.
745635Sroot  */
755635Sroot raw_disconnect(rp)
765635Sroot 	struct rawcb *rp;
775635Sroot {
788975Sroot 
796509Ssam 	rp->rcb_flags &= ~RAW_FADDR;
807517Sroot 	if (rp->rcb_socket->so_state & SS_NOFDREF)
815635Sroot 		raw_detach(rp);
825635Sroot }
835635Sroot 
848394Swnj raw_bind(so, nam)
858394Swnj 	register struct socket *so;
868394Swnj 	struct mbuf *nam;
878394Swnj {
888394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
898394Swnj 	register struct rawcb *rp;
908394Swnj 
918394Swnj 	if (ifnet == 0)
928394Swnj 		return (EADDRNOTAVAIL);
938394Swnj /* BEGIN DUBIOUS */
948394Swnj 	/*
958394Swnj 	 * Should we verify address not already in use?
968394Swnj 	 * Some say yes, others no.
978394Swnj 	 */
988394Swnj 	switch (addr->sa_family) {
998394Swnj 
10012783Ssam #ifdef INET
1018394Swnj 	case AF_IMPLINK:
10212783Ssam 	case AF_INET: {
1038394Swnj 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
1048394Swnj 		    if_ifwithaddr(addr) == 0)
1058394Swnj 			return (EADDRNOTAVAIL);
1068394Swnj 		break;
10712783Ssam 	}
10812783Ssam #endif
1098394Swnj 
1108394Swnj #ifdef PUP
1118394Swnj 	/*
1128394Swnj 	 * Curious, we convert PUP address format to internet
1138394Swnj 	 * to allow us to verify we're asking for an Ethernet
1148394Swnj 	 * interface.  This is wrong, but things are heavily
1158394Swnj 	 * oriented towards the internet addressing scheme, and
1168394Swnj 	 * converting internet to PUP would be very expensive.
1178394Swnj 	 */
1188394Swnj 	case AF_PUP: {
1198394Swnj 		struct sockaddr_pup *spup = (struct sockaddr_pup *)addr;
1208394Swnj 		struct sockaddr_in inpup;
1218394Swnj 
1229184Ssam 		bzero((caddr_t)&inpup, (unsigned)sizeof(inpup));
1238394Swnj 		inpup.sin_family = AF_INET;
12413220Ssam 		inpup.sin_addr = if_makeaddr(spup->spup_net, spup->spup_host);
1258394Swnj 		if (inpup.sin_addr.s_addr &&
1268394Swnj 		    if_ifwithaddr((struct sockaddr *)&inpup) == 0)
1278394Swnj 			return (EADDRNOTAVAIL);
1288394Swnj 		break;
1298394Swnj 	}
1308394Swnj #endif
1318394Swnj 
1328394Swnj 	default:
1338394Swnj 		return (EAFNOSUPPORT);
1348394Swnj 	}
1358394Swnj /* END DUBIOUS */
1369184Ssam 	rp = sotorawcb(so);
1378394Swnj 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr));
1388394Swnj 	rp->rcb_flags |= RAW_LADDR;
1398394Swnj 	return (0);
1408394Swnj }
1418394Swnj 
1425635Sroot /*
1435635Sroot  * Associate a peer's address with a
1445635Sroot  * raw connection block.
1455635Sroot  */
1468394Swnj raw_connaddr(rp, nam)
1475635Sroot 	struct rawcb *rp;
1488394Swnj 	struct mbuf *nam;
1495635Sroot {
1508394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
1518394Swnj 
1526509Ssam 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr));
1536509Ssam 	rp->rcb_flags |= RAW_FADDR;
1545635Sroot }
155