xref: /csrg-svn/sys/net/raw_cb.c (revision 10890)
1*10890Ssam /*	raw_cb.c	4.16	83/02/10	*/
25635Sroot 
35635Sroot #include "../h/param.h"
45635Sroot #include "../h/systm.h"
55635Sroot #include "../h/mbuf.h"
65635Sroot #include "../h/socket.h"
75635Sroot #include "../h/socketvar.h"
8*10890Ssam #include "../h/errno.h"
9*10890Ssam 
105635Sroot #include "../net/if.h"
115635Sroot #include "../net/raw_cb.h"
125635Sroot 
13*10890Ssam #include "../vax/mtpr.h"
14*10890Ssam 
155635Sroot /*
165635Sroot  * Routines to manage the raw protocol control blocks.
175635Sroot  *
185635Sroot  * TODO:
195635Sroot  *	hash lookups by protocol family/protocol + address family
206339Ssam  *	take care of unique address problems per AF?
216045Swnj  *	redo address binding to allow wildcards
225635Sroot  */
235635Sroot 
245635Sroot /*
255635Sroot  * Allocate a control block and a nominal amount
265635Sroot  * of buffer space for the socket.
275635Sroot  */
288394Swnj raw_attach(so)
295635Sroot 	register struct socket *so;
305635Sroot {
315635Sroot 	struct mbuf *m;
325635Sroot 	register struct rawcb *rp;
335635Sroot 
349638Ssam 	m = m_getclr(M_DONTWAIT, MT_PCB);
355635Sroot 	if (m == 0)
365635Sroot 		return (ENOBUFS);
375635Sroot 	if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
385635Sroot 		goto bad;
395635Sroot 	if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
405635Sroot 		goto bad2;
415635Sroot 	rp = mtod(m, struct rawcb *);
425635Sroot 	rp->rcb_socket = so;
435635Sroot 	insque(rp, &rawcb);
445635Sroot 	so->so_pcb = (caddr_t)rp;
455635Sroot 	rp->rcb_pcb = 0;
465635Sroot 	return (0);
475635Sroot bad2:
485635Sroot 	sbrelease(&so->so_snd);
495635Sroot bad:
505635Sroot 	(void) m_free(m);
515635Sroot 	return (ENOBUFS);
525635Sroot }
535635Sroot 
545635Sroot /*
555635Sroot  * Detach the raw connection block and discard
565635Sroot  * socket resources.
575635Sroot  */
585635Sroot raw_detach(rp)
595635Sroot 	register struct rawcb *rp;
605635Sroot {
615635Sroot 	struct socket *so = rp->rcb_socket;
625635Sroot 
635635Sroot 	so->so_pcb = 0;
645635Sroot 	sofree(so);
655635Sroot 	remque(rp);
668975Sroot 	m_freem(dtom(rp));
675635Sroot }
685635Sroot 
695635Sroot /*
705635Sroot  * Disconnect and possibly release resources.
715635Sroot  */
725635Sroot raw_disconnect(rp)
735635Sroot 	struct rawcb *rp;
745635Sroot {
758975Sroot 
766509Ssam 	rp->rcb_flags &= ~RAW_FADDR;
777517Sroot 	if (rp->rcb_socket->so_state & SS_NOFDREF)
785635Sroot 		raw_detach(rp);
795635Sroot }
805635Sroot 
818394Swnj raw_bind(so, nam)
828394Swnj 	register struct socket *so;
838394Swnj 	struct mbuf *nam;
848394Swnj {
858394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
868394Swnj 	register struct rawcb *rp;
878394Swnj 
888394Swnj 	if (ifnet == 0)
898394Swnj 		return (EADDRNOTAVAIL);
908394Swnj {
919184Ssam #include "../h/domain.h"
928394Swnj #include "../netinet/in.h"
938394Swnj #include "../netinet/in_systm.h"
948394Swnj /* BEGIN DUBIOUS */
958394Swnj 	/*
968394Swnj 	 * Should we verify address not already in use?
978394Swnj 	 * Some say yes, others no.
988394Swnj 	 */
998394Swnj 	switch (addr->sa_family) {
1008394Swnj 
1018394Swnj 	case AF_IMPLINK:
1028394Swnj 	case AF_INET:
1038394Swnj 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
1048394Swnj 		    if_ifwithaddr(addr) == 0)
1058394Swnj 			return (EADDRNOTAVAIL);
1068394Swnj 		break;
1078394Swnj 
1088394Swnj #ifdef PUP
1098394Swnj 	/*
1108394Swnj 	 * Curious, we convert PUP address format to internet
1118394Swnj 	 * to allow us to verify we're asking for an Ethernet
1128394Swnj 	 * interface.  This is wrong, but things are heavily
1138394Swnj 	 * oriented towards the internet addressing scheme, and
1148394Swnj 	 * converting internet to PUP would be very expensive.
1158394Swnj 	 */
1168394Swnj 	case AF_PUP: {
1178394Swnj #include "../netpup/pup.h"
1188394Swnj 		struct sockaddr_pup *spup = (struct sockaddr_pup *)addr;
1198394Swnj 		struct sockaddr_in inpup;
1208394Swnj 
1219184Ssam 		bzero((caddr_t)&inpup, (unsigned)sizeof(inpup));
1228394Swnj 		inpup.sin_family = AF_INET;
1238394Swnj 		inpup.sin_addr.s_net = spup->sp_net;
1248394Swnj 		inpup.sin_addr.s_impno = spup->sp_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 }
1368394Swnj /* END DUBIOUS */
1379184Ssam 	rp = sotorawcb(so);
1388394Swnj 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr));
1398394Swnj 	rp->rcb_flags |= RAW_LADDR;
1408394Swnj 	return (0);
1418394Swnj }
1428394Swnj 
1435635Sroot /*
1445635Sroot  * Associate a peer's address with a
1455635Sroot  * raw connection block.
1465635Sroot  */
1478394Swnj raw_connaddr(rp, nam)
1485635Sroot 	struct rawcb *rp;
1498394Swnj 	struct mbuf *nam;
1505635Sroot {
1518394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
1528394Swnj 
1536509Ssam 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr));
1546509Ssam 	rp->rcb_flags |= RAW_FADDR;
1555635Sroot }
156