xref: /csrg-svn/sys/net/raw_cb.c (revision 5772)
1*5772Swnj /*	raw_cb.c	4.3	82/02/12	*/
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"
135635Sroot #include "/usr/include/errno.h"
145635Sroot 
155635Sroot /*
165635Sroot  * Routines to manage the raw protocol control blocks.
175635Sroot  *
185635Sroot  * TODO:
195635Sroot  *	hash lookups by protocol family/protocol + address family
205635Sroot  *	take care of unique address problems per AF
215635Sroot  */
225635Sroot 
235635Sroot /*
245635Sroot  * Allocate a control block and a nominal amount
255635Sroot  * of buffer space for the socket.
265635Sroot  */
275635Sroot raw_attach(so, addr)
285635Sroot 	register struct socket *so;
295635Sroot 	struct sockaddr *addr;
305635Sroot {
315635Sroot 	struct mbuf *m;
325635Sroot 	register struct rawcb *rp;
335635Sroot 	struct ifnet *ifp = ifnet;
345635Sroot 
355635Sroot COUNT(RAW_ATTACH);
365635Sroot 	/*
375635Sroot 	 * Should we verify address not already in use?
385635Sroot 	 * Some say yes, others no.
395635Sroot 	 */
405635Sroot 	if (addr) switch (addr->sa_family) {
415635Sroot 
42*5772Swnj 	case AF_IMPLINK:
435635Sroot 	case AF_INET: {
445635Sroot 		register struct sockaddr_in *sin = (struct sockaddr_in *)addr;
455635Sroot 
465635Sroot 		if (ifnet && sin->sin_addr.s_addr == 0)
475635Sroot 			sin->sin_addr = ifnet->if_addr;
485635Sroot 		ifp = if_ifwithaddr(sin->sin_addr);
495635Sroot 		break;
505635Sroot 		}
515635Sroot 
525635Sroot 	default:
535635Sroot 		return (EAFNOSUPPORT);
545635Sroot 	}
555635Sroot 	if (ifp == 0)
565635Sroot 		return (EADDRNOTAVAIL);
575635Sroot 	m = m_getclr(M_DONTWAIT);
585635Sroot 	if (m == 0)
595635Sroot 		return (ENOBUFS);
605635Sroot 	if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
615635Sroot 		goto bad;
625635Sroot 	if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
635635Sroot 		goto bad2;
645635Sroot 	rp = mtod(m, struct rawcb *);
655635Sroot 	rp->rcb_socket = so;
665635Sroot 	insque(rp, &rawcb);
675635Sroot 	so->so_pcb = (caddr_t)rp;
685635Sroot 	rp->rcb_pcb = 0;
695635Sroot 
705635Sroot 	if (addr)
715635Sroot 		bcopy(addr, &so->so_addr, sizeof(*addr));
725635Sroot 	return (0);
735635Sroot bad2:
745635Sroot 	sbrelease(&so->so_snd);
755635Sroot bad:
765635Sroot 	(void) m_free(m);
775635Sroot 	return (ENOBUFS);
785635Sroot }
795635Sroot 
805635Sroot /*
815635Sroot  * Detach the raw connection block and discard
825635Sroot  * socket resources.
835635Sroot  */
845635Sroot raw_detach(rp)
855635Sroot 	register struct rawcb *rp;
865635Sroot {
875635Sroot 	struct socket *so = rp->rcb_socket;
885635Sroot 
895635Sroot COUNT(RAW_DETACH);
905635Sroot 	so->so_pcb = 0;
915635Sroot 	sofree(so);
925635Sroot 	remque(rp);
935635Sroot 	(void) m_freem(dtom(rp));
945635Sroot }
955635Sroot 
965635Sroot /*
975635Sroot  * Disconnect and possibly release resources.
985635Sroot  */
995635Sroot raw_disconnect(rp)
1005635Sroot 	struct rawcb *rp;
1015635Sroot {
1025635Sroot COUNT(RAW_DISCONNECT);
1035635Sroot 	rp->rcb_flags &= ~RAW_ADDR;
1045635Sroot 	if (rp->rcb_socket->so_state & SS_USERGONE)
1055635Sroot 		raw_detach(rp);
1065635Sroot }
1075635Sroot 
1085635Sroot /*
1095635Sroot  * Associate a peer's address with a
1105635Sroot  * raw connection block.
1115635Sroot  */
1125635Sroot raw_connaddr(rp, addr)
1135635Sroot 	struct rawcb *rp;
1145635Sroot 	struct sockaddr *addr;
1155635Sroot {
1165635Sroot COUNT(RAW_CONNADDR);
1175635Sroot 	bcopy(addr, &rp->rcb_addr, sizeof(struct sockaddr));
1185635Sroot 	rp->rcb_flags |= RAW_ADDR;
1195635Sroot }
120