xref: /csrg-svn/sys/net/raw_cb.c (revision 33183)
123160Smckusick /*
229066Smckusick  * Copyright (c) 1980, 1986 Regents of the University of California.
3*33183Sbostic  * All rights reserved.
423160Smckusick  *
5*33183Sbostic  * Redistribution and use in source and binary forms are permitted
6*33183Sbostic  * provided that this notice is preserved and that due credit is given
7*33183Sbostic  * to the University of California at Berkeley. The name of the University
8*33183Sbostic  * may not be used to endorse or promote products derived from this
9*33183Sbostic  * software without specific prior written permission. This software
10*33183Sbostic  * is provided ``as is'' without express or implied warranty.
11*33183Sbostic  *
12*33183Sbostic  *	@(#)raw_cb.c	7.4 (Berkeley) 12/30/87
1323160Smckusick  */
145635Sroot 
1517066Sbloom #include "param.h"
1617066Sbloom #include "systm.h"
1717066Sbloom #include "mbuf.h"
1817066Sbloom #include "socket.h"
1917066Sbloom #include "socketvar.h"
2021769Skarels #include "domain.h"
2121769Skarels #include "protosw.h"
2217066Sbloom #include "errno.h"
2310890Ssam 
2417066Sbloom #include "if.h"
2517066Sbloom #include "route.h"
2617066Sbloom #include "raw_cb.h"
2712783Ssam #include "../netinet/in.h"
285635Sroot 
2929922Skarels #include "../machine/mtpr.h"
3010890Ssam 
315635Sroot /*
325635Sroot  * Routines to manage the raw protocol control blocks.
335635Sroot  *
345635Sroot  * TODO:
355635Sroot  *	hash lookups by protocol family/protocol + address family
366339Ssam  *	take care of unique address problems per AF?
376045Swnj  *	redo address binding to allow wildcards
385635Sroot  */
395635Sroot 
405635Sroot /*
415635Sroot  * Allocate a control block and a nominal amount
425635Sroot  * of buffer space for the socket.
435635Sroot  */
4421769Skarels raw_attach(so, proto)
455635Sroot 	register struct socket *so;
4621769Skarels 	int proto;
475635Sroot {
485635Sroot 	struct mbuf *m;
495635Sroot 	register struct rawcb *rp;
505635Sroot 
519638Ssam 	m = m_getclr(M_DONTWAIT, MT_PCB);
525635Sroot 	if (m == 0)
535635Sroot 		return (ENOBUFS);
545635Sroot 	if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
555635Sroot 		goto bad;
565635Sroot 	if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
575635Sroot 		goto bad2;
585635Sroot 	rp = mtod(m, struct rawcb *);
595635Sroot 	rp->rcb_socket = so;
605635Sroot 	so->so_pcb = (caddr_t)rp;
615635Sroot 	rp->rcb_pcb = 0;
6221769Skarels 	rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family;
6321769Skarels 	rp->rcb_proto.sp_protocol = proto;
6421769Skarels 	insque(rp, &rawcb);
655635Sroot 	return (0);
665635Sroot bad2:
675635Sroot 	sbrelease(&so->so_snd);
685635Sroot bad:
695635Sroot 	(void) m_free(m);
705635Sroot 	return (ENOBUFS);
715635Sroot }
725635Sroot 
735635Sroot /*
745635Sroot  * Detach the raw connection block and discard
755635Sroot  * socket resources.
765635Sroot  */
775635Sroot raw_detach(rp)
785635Sroot 	register struct rawcb *rp;
795635Sroot {
805635Sroot 	struct socket *so = rp->rcb_socket;
815635Sroot 
8224774Skarels 	if (rp->rcb_route.ro_rt)
8324774Skarels 		rtfree(rp->rcb_route.ro_rt);
845635Sroot 	so->so_pcb = 0;
855635Sroot 	sofree(so);
865635Sroot 	remque(rp);
8726035Skarels 	if (rp->rcb_options)
8829569Skarels 		m_freem(rp->rcb_options);
898975Sroot 	m_freem(dtom(rp));
905635Sroot }
915635Sroot 
925635Sroot /*
935635Sroot  * Disconnect and possibly release resources.
945635Sroot  */
955635Sroot raw_disconnect(rp)
965635Sroot 	struct rawcb *rp;
975635Sroot {
988975Sroot 
996509Ssam 	rp->rcb_flags &= ~RAW_FADDR;
1007517Sroot 	if (rp->rcb_socket->so_state & SS_NOFDREF)
1015635Sroot 		raw_detach(rp);
1025635Sroot }
1035635Sroot 
1048394Swnj raw_bind(so, nam)
1058394Swnj 	register struct socket *so;
1068394Swnj 	struct mbuf *nam;
1078394Swnj {
1088394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
1098394Swnj 	register struct rawcb *rp;
1108394Swnj 
1118394Swnj 	if (ifnet == 0)
1128394Swnj 		return (EADDRNOTAVAIL);
1138394Swnj /* BEGIN DUBIOUS */
1148394Swnj 	/*
1158394Swnj 	 * Should we verify address not already in use?
1168394Swnj 	 * Some say yes, others no.
1178394Swnj 	 */
1188394Swnj 	switch (addr->sa_family) {
1198394Swnj 
12025647Skarels #ifdef INET
1218394Swnj 	case AF_IMPLINK:
12212783Ssam 	case AF_INET: {
1238394Swnj 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
12418409Skarels 		    ifa_ifwithaddr(addr) == 0)
1258394Swnj 			return (EADDRNOTAVAIL);
1268394Swnj 		break;
12712783Ssam 	}
12812783Ssam #endif
1298394Swnj 
1308394Swnj 	default:
1318394Swnj 		return (EAFNOSUPPORT);
1328394Swnj 	}
1338394Swnj /* END DUBIOUS */
1349184Ssam 	rp = sotorawcb(so);
1358394Swnj 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr));
1368394Swnj 	rp->rcb_flags |= RAW_LADDR;
1378394Swnj 	return (0);
1388394Swnj }
1398394Swnj 
1405635Sroot /*
1415635Sroot  * Associate a peer's address with a
1425635Sroot  * raw connection block.
1435635Sroot  */
1448394Swnj raw_connaddr(rp, nam)
1455635Sroot 	struct rawcb *rp;
1468394Swnj 	struct mbuf *nam;
1475635Sroot {
1488394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
1498394Swnj 
1506509Ssam 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr));
1516509Ssam 	rp->rcb_flags |= RAW_FADDR;
1525635Sroot }
153