xref: /csrg-svn/sys/net/raw_cb.c (revision 8975)
1*8975Sroot /*	raw_cb.c	4.13	82/10/31	*/
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*8975Sroot #include "../vax/mtpr.h"
95635Sroot #include "../net/if.h"
105635Sroot #include "../net/raw_cb.h"
117298Ssam #include <errno.h>
125635Sroot 
135635Sroot /*
145635Sroot  * Routines to manage the raw protocol control blocks.
155635Sroot  *
165635Sroot  * TODO:
175635Sroot  *	hash lookups by protocol family/protocol + address family
186339Ssam  *	take care of unique address problems per AF?
196045Swnj  *	redo address binding to allow wildcards
205635Sroot  */
215635Sroot 
225635Sroot /*
235635Sroot  * Allocate a control block and a nominal amount
245635Sroot  * of buffer space for the socket.
255635Sroot  */
268394Swnj raw_attach(so)
275635Sroot 	register struct socket *so;
285635Sroot {
295635Sroot 	struct mbuf *m;
305635Sroot 	register struct rawcb *rp;
315635Sroot 
325635Sroot 	m = m_getclr(M_DONTWAIT);
335635Sroot 	if (m == 0)
345635Sroot 		return (ENOBUFS);
355635Sroot 	if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
365635Sroot 		goto bad;
375635Sroot 	if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
385635Sroot 		goto bad2;
395635Sroot 	rp = mtod(m, struct rawcb *);
405635Sroot 	rp->rcb_socket = so;
415635Sroot 	insque(rp, &rawcb);
425635Sroot 	so->so_pcb = (caddr_t)rp;
435635Sroot 	rp->rcb_pcb = 0;
445635Sroot 	return (0);
455635Sroot bad2:
465635Sroot 	sbrelease(&so->so_snd);
475635Sroot bad:
485635Sroot 	(void) m_free(m);
495635Sroot 	return (ENOBUFS);
505635Sroot }
515635Sroot 
525635Sroot /*
535635Sroot  * Detach the raw connection block and discard
545635Sroot  * socket resources.
555635Sroot  */
565635Sroot raw_detach(rp)
575635Sroot 	register struct rawcb *rp;
585635Sroot {
595635Sroot 	struct socket *so = rp->rcb_socket;
605635Sroot 
615635Sroot 	so->so_pcb = 0;
625635Sroot 	sofree(so);
635635Sroot 	remque(rp);
64*8975Sroot 	m_freem(dtom(rp));
655635Sroot }
665635Sroot 
675635Sroot /*
685635Sroot  * Disconnect and possibly release resources.
695635Sroot  */
705635Sroot raw_disconnect(rp)
715635Sroot 	struct rawcb *rp;
725635Sroot {
73*8975Sroot 
746509Ssam 	rp->rcb_flags &= ~RAW_FADDR;
757517Sroot 	if (rp->rcb_socket->so_state & SS_NOFDREF)
765635Sroot 		raw_detach(rp);
775635Sroot }
785635Sroot 
798394Swnj raw_bind(so, nam)
808394Swnj 	register struct socket *so;
818394Swnj 	struct mbuf *nam;
828394Swnj {
838394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
848394Swnj 	register struct rawcb *rp;
858394Swnj 
868394Swnj 	if (ifnet == 0)
878394Swnj 		return (EADDRNOTAVAIL);
888394Swnj {
898394Swnj #include "../netinet/in.h"
908394Swnj #include "../netinet/in_systm.h"
918394Swnj /* BEGIN DUBIOUS */
928394Swnj 	/*
938394Swnj 	 * Should we verify address not already in use?
948394Swnj 	 * Some say yes, others no.
958394Swnj 	 */
968394Swnj 	switch (addr->sa_family) {
978394Swnj 
988394Swnj 	case AF_IMPLINK:
998394Swnj 	case AF_INET:
1008394Swnj 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
1018394Swnj 		    if_ifwithaddr(addr) == 0)
1028394Swnj 			return (EADDRNOTAVAIL);
1038394Swnj 		break;
1048394Swnj 
1058394Swnj #ifdef PUP
1068394Swnj 	/*
1078394Swnj 	 * Curious, we convert PUP address format to internet
1088394Swnj 	 * to allow us to verify we're asking for an Ethernet
1098394Swnj 	 * interface.  This is wrong, but things are heavily
1108394Swnj 	 * oriented towards the internet addressing scheme, and
1118394Swnj 	 * converting internet to PUP would be very expensive.
1128394Swnj 	 */
1138394Swnj 	case AF_PUP: {
1148394Swnj #include "../netpup/pup.h"
1158394Swnj 		struct sockaddr_pup *spup = (struct sockaddr_pup *)addr;
1168394Swnj 		struct sockaddr_in inpup;
1178394Swnj 
1188394Swnj 		bzero((caddr_t)&inpup, sizeof(inpup));
1198394Swnj 		inpup.sin_family = AF_INET;
1208394Swnj 		inpup.sin_addr.s_net = spup->sp_net;
1218394Swnj 		inpup.sin_addr.s_impno = spup->sp_host;
1228394Swnj 		if (inpup.sin_addr.s_addr &&
1238394Swnj 		    if_ifwithaddr((struct sockaddr *)&inpup) == 0)
1248394Swnj 			return (EADDRNOTAVAIL);
1258394Swnj 		break;
1268394Swnj 	}
1278394Swnj #endif
1288394Swnj 
1298394Swnj 	default:
1308394Swnj 		return (EAFNOSUPPORT);
1318394Swnj 	}
1328394Swnj }
1338394Swnj /* END DUBIOUS */
1348394Swnj 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr));
1358394Swnj 	rp->rcb_flags |= RAW_LADDR;
1368394Swnj 	return (0);
1378394Swnj }
1388394Swnj 
1395635Sroot /*
1405635Sroot  * Associate a peer's address with a
1415635Sroot  * raw connection block.
1425635Sroot  */
1438394Swnj raw_connaddr(rp, nam)
1445635Sroot 	struct rawcb *rp;
1458394Swnj 	struct mbuf *nam;
1465635Sroot {
1478394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
1488394Swnj 
1496509Ssam 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr));
1506509Ssam 	rp->rcb_flags |= RAW_FADDR;
1515635Sroot }
152