xref: /csrg-svn/sys/net/raw_cb.c (revision 6161)
1*6161Ssam /*	raw_cb.c	4.5	82/03/13	*/
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"
136045Swnj #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
216045Swnj  *	redo address binding to allow wildcards
225635Sroot  */
235635Sroot 
245635Sroot /*
255635Sroot  * Allocate a control block and a nominal amount
265635Sroot  * of buffer space for the socket.
275635Sroot  */
285635Sroot raw_attach(so, addr)
295635Sroot 	register struct socket *so;
305635Sroot 	struct sockaddr *addr;
315635Sroot {
325635Sroot 	struct mbuf *m;
335635Sroot 	register struct rawcb *rp;
345635Sroot 	struct ifnet *ifp = ifnet;
355635Sroot 
365635Sroot COUNT(RAW_ATTACH);
375635Sroot 	/*
385635Sroot 	 * Should we verify address not already in use?
395635Sroot 	 * Some say yes, others no.
405635Sroot 	 */
415635Sroot 	if (addr) switch (addr->sa_family) {
425635Sroot 
435772Swnj 	case AF_IMPLINK:
445635Sroot 	case AF_INET: {
455635Sroot 		register struct sockaddr_in *sin = (struct sockaddr_in *)addr;
465635Sroot 
475635Sroot 		if (ifnet && sin->sin_addr.s_addr == 0)
485635Sroot 			sin->sin_addr = ifnet->if_addr;
495635Sroot 		ifp = if_ifwithaddr(sin->sin_addr);
505635Sroot 		break;
515635Sroot 		}
525635Sroot 
536045Swnj 	case AF_PUP:
546045Swnj 		ifp = ifnet;
556045Swnj 		break;
566045Swnj 
575635Sroot 	default:
585635Sroot 		return (EAFNOSUPPORT);
595635Sroot 	}
605635Sroot 	if (ifp == 0)
615635Sroot 		return (EADDRNOTAVAIL);
625635Sroot 	m = m_getclr(M_DONTWAIT);
635635Sroot 	if (m == 0)
645635Sroot 		return (ENOBUFS);
655635Sroot 	if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
665635Sroot 		goto bad;
675635Sroot 	if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
685635Sroot 		goto bad2;
695635Sroot 	rp = mtod(m, struct rawcb *);
705635Sroot 	rp->rcb_socket = so;
715635Sroot 	insque(rp, &rawcb);
725635Sroot 	so->so_pcb = (caddr_t)rp;
735635Sroot 	rp->rcb_pcb = 0;
745635Sroot 
755635Sroot 	if (addr)
76*6161Ssam 		bcopy((caddr_t)addr, (caddr_t)&so->so_addr, sizeof(*addr));
775635Sroot 	return (0);
785635Sroot bad2:
795635Sroot 	sbrelease(&so->so_snd);
805635Sroot bad:
815635Sroot 	(void) m_free(m);
825635Sroot 	return (ENOBUFS);
835635Sroot }
845635Sroot 
855635Sroot /*
865635Sroot  * Detach the raw connection block and discard
875635Sroot  * socket resources.
885635Sroot  */
895635Sroot raw_detach(rp)
905635Sroot 	register struct rawcb *rp;
915635Sroot {
925635Sroot 	struct socket *so = rp->rcb_socket;
935635Sroot 
945635Sroot COUNT(RAW_DETACH);
955635Sroot 	so->so_pcb = 0;
965635Sroot 	sofree(so);
975635Sroot 	remque(rp);
98*6161Ssam 	m_freem(dtom(rp));
995635Sroot }
1005635Sroot 
1015635Sroot /*
1025635Sroot  * Disconnect and possibly release resources.
1035635Sroot  */
1045635Sroot raw_disconnect(rp)
1055635Sroot 	struct rawcb *rp;
1065635Sroot {
1075635Sroot COUNT(RAW_DISCONNECT);
1085635Sroot 	rp->rcb_flags &= ~RAW_ADDR;
1095635Sroot 	if (rp->rcb_socket->so_state & SS_USERGONE)
1105635Sroot 		raw_detach(rp);
1115635Sroot }
1125635Sroot 
1135635Sroot /*
1145635Sroot  * Associate a peer's address with a
1155635Sroot  * raw connection block.
1165635Sroot  */
1175635Sroot raw_connaddr(rp, addr)
1185635Sroot 	struct rawcb *rp;
1195635Sroot 	struct sockaddr *addr;
1205635Sroot {
1215635Sroot COUNT(RAW_CONNADDR);
122*6161Ssam 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_addr, sizeof(struct sockaddr));
1235635Sroot 	rp->rcb_flags |= RAW_ADDR;
1245635Sroot }
125