xref: /csrg-svn/sys/net/raw_cb.c (revision 6529)
1*6529Ssam /*	raw_cb.c	4.8	82/04/11	*/
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"
85635Sroot #include "../h/mtpr.h"
95635Sroot #include "../net/in.h"
105635Sroot #include "../net/in_systm.h"
115635Sroot #include "../net/if.h"
125635Sroot #include "../net/raw_cb.h"
136339Ssam #include "../net/pup.h"
146045Swnj #include "../errno.h"
155635Sroot 
165635Sroot /*
175635Sroot  * Routines to manage the raw protocol control blocks.
185635Sroot  *
195635Sroot  * TODO:
205635Sroot  *	hash lookups by protocol family/protocol + address family
216339Ssam  *	take care of unique address problems per AF?
226045Swnj  *	redo address binding to allow wildcards
235635Sroot  */
245635Sroot 
255635Sroot /*
265635Sroot  * Allocate a control block and a nominal amount
275635Sroot  * of buffer space for the socket.
285635Sroot  */
295635Sroot raw_attach(so, addr)
305635Sroot 	register struct socket *so;
315635Sroot 	struct sockaddr *addr;
325635Sroot {
335635Sroot 	struct mbuf *m;
345635Sroot 	register struct rawcb *rp;
355635Sroot 
365635Sroot COUNT(RAW_ATTACH);
376339Ssam 	if (ifnet == 0)
386339Ssam 		return (EADDRNOTAVAIL);
395635Sroot 	/*
405635Sroot 	 * Should we verify address not already in use?
415635Sroot 	 * Some say yes, others no.
425635Sroot 	 */
435635Sroot 	if (addr) switch (addr->sa_family) {
445635Sroot 
455772Swnj 	case AF_IMPLINK:
466339Ssam 	case AF_INET:
476339Ssam 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
486339Ssam 		    if_ifwithaddr(addr) == 0)
496339Ssam 			return (EADDRNOTAVAIL);
505635Sroot 		break;
515635Sroot 
526339Ssam #ifdef PUP
536339Ssam 	/*
546339Ssam 	 * Curious, we convert PUP address format to internet
556339Ssam 	 * to allow us to verify we're asking for an Ethernet
566339Ssam 	 * interface.  This is wrong, but things are heavily
576339Ssam 	 * oriented towards the internet addressing scheme, and
586339Ssam 	 * converting internet to PUP would be very expensive.
596339Ssam 	 */
606339Ssam 	case AF_PUP: {
616339Ssam 		struct sockaddr_pup *spup = (struct sockaddr_pup *)addr;
626339Ssam 		struct sockaddr_in inpup;
636339Ssam 
646339Ssam 		bzero((caddr_t)&inpup, sizeof(inpup));
656509Ssam 		inpup.sin_family = AF_INET;
666339Ssam 		inpup.sin_addr.s_net = spup->sp_net;
676339Ssam 		inpup.sin_addr.s_impno = spup->sp_host;
686339Ssam 		if (inpup.sin_addr.s_addr &&
696339Ssam 		    if_ifwithaddr((struct sockaddr *)&inpup) == 0)
706339Ssam 			return (EADDRNOTAVAIL);
716045Swnj 		break;
726339Ssam 	}
736339Ssam #endif
746045Swnj 
755635Sroot 	default:
765635Sroot 		return (EAFNOSUPPORT);
775635Sroot 	}
785635Sroot 	m = m_getclr(M_DONTWAIT);
795635Sroot 	if (m == 0)
805635Sroot 		return (ENOBUFS);
815635Sroot 	if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
825635Sroot 		goto bad;
835635Sroot 	if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
845635Sroot 		goto bad2;
855635Sroot 	rp = mtod(m, struct rawcb *);
865635Sroot 	rp->rcb_socket = so;
875635Sroot 	insque(rp, &rawcb);
885635Sroot 	so->so_pcb = (caddr_t)rp;
895635Sroot 	rp->rcb_pcb = 0;
90*6529Ssam 	if (addr) {
916509Ssam 		bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof(*addr));
92*6529Ssam 		rp->rcb_flags |= RAW_LADDR;
93*6529Ssam 	}
945635Sroot 	return (0);
955635Sroot bad2:
965635Sroot 	sbrelease(&so->so_snd);
975635Sroot bad:
985635Sroot 	(void) m_free(m);
995635Sroot 	return (ENOBUFS);
1005635Sroot }
1015635Sroot 
1025635Sroot /*
1035635Sroot  * Detach the raw connection block and discard
1045635Sroot  * socket resources.
1055635Sroot  */
1065635Sroot raw_detach(rp)
1075635Sroot 	register struct rawcb *rp;
1085635Sroot {
1095635Sroot 	struct socket *so = rp->rcb_socket;
1105635Sroot 
1115635Sroot COUNT(RAW_DETACH);
1125635Sroot 	so->so_pcb = 0;
1135635Sroot 	sofree(so);
1145635Sroot 	remque(rp);
1156339Ssam 	(void) m_freem(dtom(rp));
1165635Sroot }
1175635Sroot 
1185635Sroot /*
1195635Sroot  * Disconnect and possibly release resources.
1205635Sroot  */
1215635Sroot raw_disconnect(rp)
1225635Sroot 	struct rawcb *rp;
1235635Sroot {
1245635Sroot COUNT(RAW_DISCONNECT);
1256509Ssam 	rp->rcb_flags &= ~RAW_FADDR;
1265635Sroot 	if (rp->rcb_socket->so_state & SS_USERGONE)
1275635Sroot 		raw_detach(rp);
1285635Sroot }
1295635Sroot 
1305635Sroot /*
1315635Sroot  * Associate a peer's address with a
1325635Sroot  * raw connection block.
1335635Sroot  */
1345635Sroot raw_connaddr(rp, addr)
1355635Sroot 	struct rawcb *rp;
1365635Sroot 	struct sockaddr *addr;
1375635Sroot {
1385635Sroot COUNT(RAW_CONNADDR);
1396509Ssam 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr));
1406509Ssam 	rp->rcb_flags |= RAW_FADDR;
1415635Sroot }
142