xref: /csrg-svn/sys/net/raw_cb.c (revision 12783)
1*12783Ssam /*	raw_cb.c	4.17	83/05/27	*/
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"
810890Ssam #include "../h/errno.h"
910890Ssam 
105635Sroot #include "../net/if.h"
115635Sroot #include "../net/raw_cb.h"
12*12783Ssam #include "../netinet/in.h"
13*12783Ssam #include "../netpup/pup.h"
145635Sroot 
1510890Ssam #include "../vax/mtpr.h"
1610890Ssam 
175635Sroot /*
185635Sroot  * Routines to manage the raw protocol control blocks.
195635Sroot  *
205635Sroot  * TODO:
215635Sroot  *	hash lookups by protocol family/protocol + address family
226339Ssam  *	take care of unique address problems per AF?
236045Swnj  *	redo address binding to allow wildcards
245635Sroot  */
255635Sroot 
265635Sroot /*
275635Sroot  * Allocate a control block and a nominal amount
285635Sroot  * of buffer space for the socket.
295635Sroot  */
308394Swnj raw_attach(so)
315635Sroot 	register struct socket *so;
325635Sroot {
335635Sroot 	struct mbuf *m;
345635Sroot 	register struct rawcb *rp;
355635Sroot 
369638Ssam 	m = m_getclr(M_DONTWAIT, MT_PCB);
375635Sroot 	if (m == 0)
385635Sroot 		return (ENOBUFS);
395635Sroot 	if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
405635Sroot 		goto bad;
415635Sroot 	if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
425635Sroot 		goto bad2;
435635Sroot 	rp = mtod(m, struct rawcb *);
445635Sroot 	rp->rcb_socket = so;
455635Sroot 	insque(rp, &rawcb);
465635Sroot 	so->so_pcb = (caddr_t)rp;
475635Sroot 	rp->rcb_pcb = 0;
485635Sroot 	return (0);
495635Sroot bad2:
505635Sroot 	sbrelease(&so->so_snd);
515635Sroot bad:
525635Sroot 	(void) m_free(m);
535635Sroot 	return (ENOBUFS);
545635Sroot }
555635Sroot 
565635Sroot /*
575635Sroot  * Detach the raw connection block and discard
585635Sroot  * socket resources.
595635Sroot  */
605635Sroot raw_detach(rp)
615635Sroot 	register struct rawcb *rp;
625635Sroot {
635635Sroot 	struct socket *so = rp->rcb_socket;
645635Sroot 
655635Sroot 	so->so_pcb = 0;
665635Sroot 	sofree(so);
675635Sroot 	remque(rp);
688975Sroot 	m_freem(dtom(rp));
695635Sroot }
705635Sroot 
715635Sroot /*
725635Sroot  * Disconnect and possibly release resources.
735635Sroot  */
745635Sroot raw_disconnect(rp)
755635Sroot 	struct rawcb *rp;
765635Sroot {
778975Sroot 
786509Ssam 	rp->rcb_flags &= ~RAW_FADDR;
797517Sroot 	if (rp->rcb_socket->so_state & SS_NOFDREF)
805635Sroot 		raw_detach(rp);
815635Sroot }
825635Sroot 
838394Swnj raw_bind(so, nam)
848394Swnj 	register struct socket *so;
858394Swnj 	struct mbuf *nam;
868394Swnj {
878394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
888394Swnj 	register struct rawcb *rp;
898394Swnj 
908394Swnj 	if (ifnet == 0)
918394Swnj 		return (EADDRNOTAVAIL);
928394Swnj /* BEGIN DUBIOUS */
938394Swnj 	/*
948394Swnj 	 * Should we verify address not already in use?
958394Swnj 	 * Some say yes, others no.
968394Swnj 	 */
978394Swnj 	switch (addr->sa_family) {
988394Swnj 
99*12783Ssam #ifdef INET
1008394Swnj 	case AF_IMPLINK:
101*12783Ssam 	case AF_INET: {
1028394Swnj 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
1038394Swnj 		    if_ifwithaddr(addr) == 0)
1048394Swnj 			return (EADDRNOTAVAIL);
1058394Swnj 		break;
106*12783Ssam 	}
107*12783Ssam #endif
1088394Swnj 
1098394Swnj #ifdef PUP
1108394Swnj 	/*
1118394Swnj 	 * Curious, we convert PUP address format to internet
1128394Swnj 	 * to allow us to verify we're asking for an Ethernet
1138394Swnj 	 * interface.  This is wrong, but things are heavily
1148394Swnj 	 * oriented towards the internet addressing scheme, and
1158394Swnj 	 * converting internet to PUP would be very expensive.
1168394Swnj 	 */
1178394Swnj 	case AF_PUP: {
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 /* 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