xref: /csrg-svn/sys/net/raw_cb.c (revision 19948)
1*19948Sbloom /*	raw_cb.c	6.4	85/05/04	*/
25635Sroot 
317066Sbloom #include "param.h"
417066Sbloom #include "systm.h"
517066Sbloom #include "mbuf.h"
617066Sbloom #include "socket.h"
717066Sbloom #include "socketvar.h"
817066Sbloom #include "errno.h"
910890Ssam 
1017066Sbloom #include "if.h"
1117066Sbloom #include "route.h"
1217066Sbloom #include "raw_cb.h"
1312783Ssam #include "../netinet/in.h"
14*19948Sbloom #ifdef PUP
1512783Ssam #include "../netpup/pup.h"
16*19948Sbloom #endif
175635Sroot 
1810890Ssam #include "../vax/mtpr.h"
1910890Ssam 
205635Sroot /*
215635Sroot  * Routines to manage the raw protocol control blocks.
225635Sroot  *
235635Sroot  * TODO:
245635Sroot  *	hash lookups by protocol family/protocol + address family
256339Ssam  *	take care of unique address problems per AF?
266045Swnj  *	redo address binding to allow wildcards
275635Sroot  */
285635Sroot 
295635Sroot /*
305635Sroot  * Allocate a control block and a nominal amount
315635Sroot  * of buffer space for the socket.
325635Sroot  */
338394Swnj raw_attach(so)
345635Sroot 	register struct socket *so;
355635Sroot {
365635Sroot 	struct mbuf *m;
375635Sroot 	register struct rawcb *rp;
385635Sroot 
399638Ssam 	m = m_getclr(M_DONTWAIT, MT_PCB);
405635Sroot 	if (m == 0)
415635Sroot 		return (ENOBUFS);
425635Sroot 	if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
435635Sroot 		goto bad;
445635Sroot 	if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
455635Sroot 		goto bad2;
465635Sroot 	rp = mtod(m, struct rawcb *);
475635Sroot 	rp->rcb_socket = so;
485635Sroot 	insque(rp, &rawcb);
495635Sroot 	so->so_pcb = (caddr_t)rp;
505635Sroot 	rp->rcb_pcb = 0;
515635Sroot 	return (0);
525635Sroot bad2:
535635Sroot 	sbrelease(&so->so_snd);
545635Sroot bad:
555635Sroot 	(void) m_free(m);
565635Sroot 	return (ENOBUFS);
575635Sroot }
585635Sroot 
595635Sroot /*
605635Sroot  * Detach the raw connection block and discard
615635Sroot  * socket resources.
625635Sroot  */
635635Sroot raw_detach(rp)
645635Sroot 	register struct rawcb *rp;
655635Sroot {
665635Sroot 	struct socket *so = rp->rcb_socket;
675635Sroot 
685635Sroot 	so->so_pcb = 0;
695635Sroot 	sofree(so);
705635Sroot 	remque(rp);
718975Sroot 	m_freem(dtom(rp));
725635Sroot }
735635Sroot 
745635Sroot /*
755635Sroot  * Disconnect and possibly release resources.
765635Sroot  */
775635Sroot raw_disconnect(rp)
785635Sroot 	struct rawcb *rp;
795635Sroot {
808975Sroot 
816509Ssam 	rp->rcb_flags &= ~RAW_FADDR;
827517Sroot 	if (rp->rcb_socket->so_state & SS_NOFDREF)
835635Sroot 		raw_detach(rp);
845635Sroot }
855635Sroot 
868394Swnj raw_bind(so, nam)
878394Swnj 	register struct socket *so;
888394Swnj 	struct mbuf *nam;
898394Swnj {
908394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
918394Swnj 	register struct rawcb *rp;
928394Swnj 
938394Swnj 	if (ifnet == 0)
948394Swnj 		return (EADDRNOTAVAIL);
958394Swnj /* BEGIN DUBIOUS */
968394Swnj 	/*
978394Swnj 	 * Should we verify address not already in use?
988394Swnj 	 * Some say yes, others no.
998394Swnj 	 */
1008394Swnj 	switch (addr->sa_family) {
1018394Swnj 
10212783Ssam #ifdef INET
1038394Swnj 	case AF_IMPLINK:
10412783Ssam 	case AF_INET: {
1058394Swnj 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
10618409Skarels 		    ifa_ifwithaddr(addr) == 0)
1078394Swnj 			return (EADDRNOTAVAIL);
1088394Swnj 		break;
10912783Ssam 	}
11012783Ssam #endif
1118394Swnj 
1128394Swnj #ifdef PUP
1138394Swnj 	/*
1148394Swnj 	 * Curious, we convert PUP address format to internet
1158394Swnj 	 * to allow us to verify we're asking for an Ethernet
1168394Swnj 	 * interface.  This is wrong, but things are heavily
1178394Swnj 	 * oriented towards the internet addressing scheme, and
1188394Swnj 	 * converting internet to PUP would be very expensive.
1198394Swnj 	 */
1208394Swnj 	case AF_PUP: {
1218394Swnj 		struct sockaddr_pup *spup = (struct sockaddr_pup *)addr;
1228394Swnj 		struct sockaddr_in inpup;
1238394Swnj 
1249184Ssam 		bzero((caddr_t)&inpup, (unsigned)sizeof(inpup));
1258394Swnj 		inpup.sin_family = AF_INET;
12618409Skarels 		inpup.sin_addr = in_makeaddr(spup->spup_net, spup->spup_host);
1278394Swnj 		if (inpup.sin_addr.s_addr &&
12818409Skarels 		    ifa_ifwithaddr((struct sockaddr *)&inpup) == 0)
1298394Swnj 			return (EADDRNOTAVAIL);
1308394Swnj 		break;
1318394Swnj 	}
1328394Swnj #endif
1338394Swnj 
1348394Swnj 	default:
1358394Swnj 		return (EAFNOSUPPORT);
1368394Swnj 	}
1378394Swnj /* END DUBIOUS */
1389184Ssam 	rp = sotorawcb(so);
1398394Swnj 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr));
1408394Swnj 	rp->rcb_flags |= RAW_LADDR;
1418394Swnj 	return (0);
1428394Swnj }
1438394Swnj 
1445635Sroot /*
1455635Sroot  * Associate a peer's address with a
1465635Sroot  * raw connection block.
1475635Sroot  */
1488394Swnj raw_connaddr(rp, nam)
1495635Sroot 	struct rawcb *rp;
1508394Swnj 	struct mbuf *nam;
1515635Sroot {
1528394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
1538394Swnj 
1546509Ssam 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr));
1556509Ssam 	rp->rcb_flags |= RAW_FADDR;
1565635Sroot }
157