xref: /csrg-svn/sys/net/raw_cb.c (revision 29922)
123160Smckusick /*
229066Smckusick  * Copyright (c) 1980, 1986 Regents of the University of California.
323160Smckusick  * All rights reserved.  The Berkeley software License Agreement
423160Smckusick  * specifies the terms and conditions for redistribution.
523160Smckusick  *
6*29922Skarels  *	@(#)raw_cb.c	7.3 (Berkeley) 10/28/86
723160Smckusick  */
85635Sroot 
917066Sbloom #include "param.h"
1017066Sbloom #include "systm.h"
1117066Sbloom #include "mbuf.h"
1217066Sbloom #include "socket.h"
1317066Sbloom #include "socketvar.h"
1421769Skarels #include "domain.h"
1521769Skarels #include "protosw.h"
1617066Sbloom #include "errno.h"
1710890Ssam 
1817066Sbloom #include "if.h"
1917066Sbloom #include "route.h"
2017066Sbloom #include "raw_cb.h"
2112783Ssam #include "../netinet/in.h"
225635Sroot 
23*29922Skarels #include "../machine/mtpr.h"
2410890Ssam 
255635Sroot /*
265635Sroot  * Routines to manage the raw protocol control blocks.
275635Sroot  *
285635Sroot  * TODO:
295635Sroot  *	hash lookups by protocol family/protocol + address family
306339Ssam  *	take care of unique address problems per AF?
316045Swnj  *	redo address binding to allow wildcards
325635Sroot  */
335635Sroot 
345635Sroot /*
355635Sroot  * Allocate a control block and a nominal amount
365635Sroot  * of buffer space for the socket.
375635Sroot  */
3821769Skarels raw_attach(so, proto)
395635Sroot 	register struct socket *so;
4021769Skarels 	int proto;
415635Sroot {
425635Sroot 	struct mbuf *m;
435635Sroot 	register struct rawcb *rp;
445635Sroot 
459638Ssam 	m = m_getclr(M_DONTWAIT, MT_PCB);
465635Sroot 	if (m == 0)
475635Sroot 		return (ENOBUFS);
485635Sroot 	if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
495635Sroot 		goto bad;
505635Sroot 	if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
515635Sroot 		goto bad2;
525635Sroot 	rp = mtod(m, struct rawcb *);
535635Sroot 	rp->rcb_socket = so;
545635Sroot 	so->so_pcb = (caddr_t)rp;
555635Sroot 	rp->rcb_pcb = 0;
5621769Skarels 	rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family;
5721769Skarels 	rp->rcb_proto.sp_protocol = proto;
5821769Skarels 	insque(rp, &rawcb);
595635Sroot 	return (0);
605635Sroot bad2:
615635Sroot 	sbrelease(&so->so_snd);
625635Sroot bad:
635635Sroot 	(void) m_free(m);
645635Sroot 	return (ENOBUFS);
655635Sroot }
665635Sroot 
675635Sroot /*
685635Sroot  * Detach the raw connection block and discard
695635Sroot  * socket resources.
705635Sroot  */
715635Sroot raw_detach(rp)
725635Sroot 	register struct rawcb *rp;
735635Sroot {
745635Sroot 	struct socket *so = rp->rcb_socket;
755635Sroot 
7624774Skarels 	if (rp->rcb_route.ro_rt)
7724774Skarels 		rtfree(rp->rcb_route.ro_rt);
785635Sroot 	so->so_pcb = 0;
795635Sroot 	sofree(so);
805635Sroot 	remque(rp);
8126035Skarels 	if (rp->rcb_options)
8229569Skarels 		m_freem(rp->rcb_options);
838975Sroot 	m_freem(dtom(rp));
845635Sroot }
855635Sroot 
865635Sroot /*
875635Sroot  * Disconnect and possibly release resources.
885635Sroot  */
895635Sroot raw_disconnect(rp)
905635Sroot 	struct rawcb *rp;
915635Sroot {
928975Sroot 
936509Ssam 	rp->rcb_flags &= ~RAW_FADDR;
947517Sroot 	if (rp->rcb_socket->so_state & SS_NOFDREF)
955635Sroot 		raw_detach(rp);
965635Sroot }
975635Sroot 
988394Swnj raw_bind(so, nam)
998394Swnj 	register struct socket *so;
1008394Swnj 	struct mbuf *nam;
1018394Swnj {
1028394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
1038394Swnj 	register struct rawcb *rp;
1048394Swnj 
1058394Swnj 	if (ifnet == 0)
1068394Swnj 		return (EADDRNOTAVAIL);
1078394Swnj /* BEGIN DUBIOUS */
1088394Swnj 	/*
1098394Swnj 	 * Should we verify address not already in use?
1108394Swnj 	 * Some say yes, others no.
1118394Swnj 	 */
1128394Swnj 	switch (addr->sa_family) {
1138394Swnj 
11425647Skarels #ifdef INET
1158394Swnj 	case AF_IMPLINK:
11612783Ssam 	case AF_INET: {
1178394Swnj 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
11818409Skarels 		    ifa_ifwithaddr(addr) == 0)
1198394Swnj 			return (EADDRNOTAVAIL);
1208394Swnj 		break;
12112783Ssam 	}
12212783Ssam #endif
1238394Swnj 
1248394Swnj 	default:
1258394Swnj 		return (EAFNOSUPPORT);
1268394Swnj 	}
1278394Swnj /* END DUBIOUS */
1289184Ssam 	rp = sotorawcb(so);
1298394Swnj 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr));
1308394Swnj 	rp->rcb_flags |= RAW_LADDR;
1318394Swnj 	return (0);
1328394Swnj }
1338394Swnj 
1345635Sroot /*
1355635Sroot  * Associate a peer's address with a
1365635Sroot  * raw connection block.
1375635Sroot  */
1388394Swnj raw_connaddr(rp, nam)
1395635Sroot 	struct rawcb *rp;
1408394Swnj 	struct mbuf *nam;
1415635Sroot {
1428394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
1438394Swnj 
1446509Ssam 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr));
1456509Ssam 	rp->rcb_flags |= RAW_FADDR;
1465635Sroot }
147