xref: /csrg-svn/sys/net/raw_cb.c (revision 21769)
1*21769Skarels /*	raw_cb.c	6.5	85/06/02	*/
25635Sroot 
317066Sbloom #include "param.h"
417066Sbloom #include "systm.h"
517066Sbloom #include "mbuf.h"
617066Sbloom #include "socket.h"
717066Sbloom #include "socketvar.h"
8*21769Skarels #include "domain.h"
9*21769Skarels #include "protosw.h"
1017066Sbloom #include "errno.h"
1110890Ssam 
1217066Sbloom #include "if.h"
1317066Sbloom #include "route.h"
1417066Sbloom #include "raw_cb.h"
1512783Ssam #include "../netinet/in.h"
1619948Sbloom #ifdef PUP
1712783Ssam #include "../netpup/pup.h"
1819948Sbloom #endif
195635Sroot 
2010890Ssam #include "../vax/mtpr.h"
2110890Ssam 
225635Sroot /*
235635Sroot  * Routines to manage the raw protocol control blocks.
245635Sroot  *
255635Sroot  * TODO:
265635Sroot  *	hash lookups by protocol family/protocol + address family
276339Ssam  *	take care of unique address problems per AF?
286045Swnj  *	redo address binding to allow wildcards
295635Sroot  */
305635Sroot 
315635Sroot /*
325635Sroot  * Allocate a control block and a nominal amount
335635Sroot  * of buffer space for the socket.
345635Sroot  */
35*21769Skarels raw_attach(so, proto)
365635Sroot 	register struct socket *so;
37*21769Skarels 	int proto;
385635Sroot {
395635Sroot 	struct mbuf *m;
405635Sroot 	register struct rawcb *rp;
415635Sroot 
429638Ssam 	m = m_getclr(M_DONTWAIT, MT_PCB);
435635Sroot 	if (m == 0)
445635Sroot 		return (ENOBUFS);
455635Sroot 	if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
465635Sroot 		goto bad;
475635Sroot 	if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
485635Sroot 		goto bad2;
495635Sroot 	rp = mtod(m, struct rawcb *);
505635Sroot 	rp->rcb_socket = so;
515635Sroot 	so->so_pcb = (caddr_t)rp;
525635Sroot 	rp->rcb_pcb = 0;
53*21769Skarels 	rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family;
54*21769Skarels 	rp->rcb_proto.sp_protocol = proto;
55*21769Skarels 	insque(rp, &rawcb);
565635Sroot 	return (0);
575635Sroot bad2:
585635Sroot 	sbrelease(&so->so_snd);
595635Sroot bad:
605635Sroot 	(void) m_free(m);
615635Sroot 	return (ENOBUFS);
625635Sroot }
635635Sroot 
645635Sroot /*
655635Sroot  * Detach the raw connection block and discard
665635Sroot  * socket resources.
675635Sroot  */
685635Sroot raw_detach(rp)
695635Sroot 	register struct rawcb *rp;
705635Sroot {
715635Sroot 	struct socket *so = rp->rcb_socket;
725635Sroot 
735635Sroot 	so->so_pcb = 0;
745635Sroot 	sofree(so);
755635Sroot 	remque(rp);
768975Sroot 	m_freem(dtom(rp));
775635Sroot }
785635Sroot 
795635Sroot /*
805635Sroot  * Disconnect and possibly release resources.
815635Sroot  */
825635Sroot raw_disconnect(rp)
835635Sroot 	struct rawcb *rp;
845635Sroot {
858975Sroot 
866509Ssam 	rp->rcb_flags &= ~RAW_FADDR;
877517Sroot 	if (rp->rcb_socket->so_state & SS_NOFDREF)
885635Sroot 		raw_detach(rp);
895635Sroot }
905635Sroot 
918394Swnj raw_bind(so, nam)
928394Swnj 	register struct socket *so;
938394Swnj 	struct mbuf *nam;
948394Swnj {
958394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
968394Swnj 	register struct rawcb *rp;
978394Swnj 
988394Swnj 	if (ifnet == 0)
998394Swnj 		return (EADDRNOTAVAIL);
1008394Swnj /* BEGIN DUBIOUS */
1018394Swnj 	/*
1028394Swnj 	 * Should we verify address not already in use?
1038394Swnj 	 * Some say yes, others no.
1048394Swnj 	 */
1058394Swnj 	switch (addr->sa_family) {
1068394Swnj 
10712783Ssam #ifdef INET
1088394Swnj 	case AF_IMPLINK:
10912783Ssam 	case AF_INET: {
1108394Swnj 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
11118409Skarels 		    ifa_ifwithaddr(addr) == 0)
1128394Swnj 			return (EADDRNOTAVAIL);
1138394Swnj 		break;
11412783Ssam 	}
11512783Ssam #endif
1168394Swnj 
1178394Swnj #ifdef PUP
1188394Swnj 	/*
1198394Swnj 	 * Curious, we convert PUP address format to internet
1208394Swnj 	 * to allow us to verify we're asking for an Ethernet
1218394Swnj 	 * interface.  This is wrong, but things are heavily
1228394Swnj 	 * oriented towards the internet addressing scheme, and
1238394Swnj 	 * converting internet to PUP would be very expensive.
1248394Swnj 	 */
1258394Swnj 	case AF_PUP: {
1268394Swnj 		struct sockaddr_pup *spup = (struct sockaddr_pup *)addr;
1278394Swnj 		struct sockaddr_in inpup;
1288394Swnj 
1299184Ssam 		bzero((caddr_t)&inpup, (unsigned)sizeof(inpup));
1308394Swnj 		inpup.sin_family = AF_INET;
13118409Skarels 		inpup.sin_addr = in_makeaddr(spup->spup_net, spup->spup_host);
1328394Swnj 		if (inpup.sin_addr.s_addr &&
13318409Skarels 		    ifa_ifwithaddr((struct sockaddr *)&inpup) == 0)
1348394Swnj 			return (EADDRNOTAVAIL);
1358394Swnj 		break;
1368394Swnj 	}
1378394Swnj #endif
1388394Swnj 
1398394Swnj 	default:
1408394Swnj 		return (EAFNOSUPPORT);
1418394Swnj 	}
1428394Swnj /* END DUBIOUS */
1439184Ssam 	rp = sotorawcb(so);
1448394Swnj 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr));
1458394Swnj 	rp->rcb_flags |= RAW_LADDR;
1468394Swnj 	return (0);
1478394Swnj }
1488394Swnj 
1495635Sroot /*
1505635Sroot  * Associate a peer's address with a
1515635Sroot  * raw connection block.
1525635Sroot  */
1538394Swnj raw_connaddr(rp, nam)
1545635Sroot 	struct rawcb *rp;
1558394Swnj 	struct mbuf *nam;
1565635Sroot {
1578394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
1588394Swnj 
1596509Ssam 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr));
1606509Ssam 	rp->rcb_flags |= RAW_FADDR;
1615635Sroot }
162