xref: /csrg-svn/sys/net/raw_cb.c (revision 9638)
1*9638Ssam /*	raw_cb.c	4.15	82/12/14	*/
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"
88975Sroot #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 
32*9638Ssam 	m = m_getclr(M_DONTWAIT, MT_PCB);
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);
648975Sroot 	m_freem(dtom(rp));
655635Sroot }
665635Sroot 
675635Sroot /*
685635Sroot  * Disconnect and possibly release resources.
695635Sroot  */
705635Sroot raw_disconnect(rp)
715635Sroot 	struct rawcb *rp;
725635Sroot {
738975Sroot 
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 {
899184Ssam #include "../h/domain.h"
908394Swnj #include "../netinet/in.h"
918394Swnj #include "../netinet/in_systm.h"
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 
998394Swnj 	case AF_IMPLINK:
1008394Swnj 	case AF_INET:
1018394Swnj 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
1028394Swnj 		    if_ifwithaddr(addr) == 0)
1038394Swnj 			return (EADDRNOTAVAIL);
1048394Swnj 		break;
1058394Swnj 
1068394Swnj #ifdef PUP
1078394Swnj 	/*
1088394Swnj 	 * Curious, we convert PUP address format to internet
1098394Swnj 	 * to allow us to verify we're asking for an Ethernet
1108394Swnj 	 * interface.  This is wrong, but things are heavily
1118394Swnj 	 * oriented towards the internet addressing scheme, and
1128394Swnj 	 * converting internet to PUP would be very expensive.
1138394Swnj 	 */
1148394Swnj 	case AF_PUP: {
1158394Swnj #include "../netpup/pup.h"
1168394Swnj 		struct sockaddr_pup *spup = (struct sockaddr_pup *)addr;
1178394Swnj 		struct sockaddr_in inpup;
1188394Swnj 
1199184Ssam 		bzero((caddr_t)&inpup, (unsigned)sizeof(inpup));
1208394Swnj 		inpup.sin_family = AF_INET;
1218394Swnj 		inpup.sin_addr.s_net = spup->sp_net;
1228394Swnj 		inpup.sin_addr.s_impno = spup->sp_host;
1238394Swnj 		if (inpup.sin_addr.s_addr &&
1248394Swnj 		    if_ifwithaddr((struct sockaddr *)&inpup) == 0)
1258394Swnj 			return (EADDRNOTAVAIL);
1268394Swnj 		break;
1278394Swnj 	}
1288394Swnj #endif
1298394Swnj 
1308394Swnj 	default:
1318394Swnj 		return (EAFNOSUPPORT);
1328394Swnj 	}
1338394Swnj }
1348394Swnj /* END DUBIOUS */
1359184Ssam 	rp = sotorawcb(so);
1368394Swnj 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr));
1378394Swnj 	rp->rcb_flags |= RAW_LADDR;
1388394Swnj 	return (0);
1398394Swnj }
1408394Swnj 
1415635Sroot /*
1425635Sroot  * Associate a peer's address with a
1435635Sroot  * raw connection block.
1445635Sroot  */
1458394Swnj raw_connaddr(rp, nam)
1465635Sroot 	struct rawcb *rp;
1478394Swnj 	struct mbuf *nam;
1485635Sroot {
1498394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
1508394Swnj 
1516509Ssam 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr));
1526509Ssam 	rp->rcb_flags |= RAW_FADDR;
1535635Sroot }
154