xref: /csrg-svn/sys/net/raw_cb.c (revision 24774)
123160Smckusick /*
223160Smckusick  * Copyright (c) 1980 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*24774Skarels  *	@(#)raw_cb.c	6.7 (Berkeley) 09/16/85
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"
2219948Sbloom #ifdef PUP
2312783Ssam #include "../netpup/pup.h"
2419948Sbloom #endif
255635Sroot 
2610890Ssam #include "../vax/mtpr.h"
2710890Ssam 
285635Sroot /*
295635Sroot  * Routines to manage the raw protocol control blocks.
305635Sroot  *
315635Sroot  * TODO:
325635Sroot  *	hash lookups by protocol family/protocol + address family
336339Ssam  *	take care of unique address problems per AF?
346045Swnj  *	redo address binding to allow wildcards
355635Sroot  */
365635Sroot 
375635Sroot /*
385635Sroot  * Allocate a control block and a nominal amount
395635Sroot  * of buffer space for the socket.
405635Sroot  */
4121769Skarels raw_attach(so, proto)
425635Sroot 	register struct socket *so;
4321769Skarels 	int proto;
445635Sroot {
455635Sroot 	struct mbuf *m;
465635Sroot 	register struct rawcb *rp;
475635Sroot 
489638Ssam 	m = m_getclr(M_DONTWAIT, MT_PCB);
495635Sroot 	if (m == 0)
505635Sroot 		return (ENOBUFS);
515635Sroot 	if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
525635Sroot 		goto bad;
535635Sroot 	if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
545635Sroot 		goto bad2;
555635Sroot 	rp = mtod(m, struct rawcb *);
565635Sroot 	rp->rcb_socket = so;
575635Sroot 	so->so_pcb = (caddr_t)rp;
585635Sroot 	rp->rcb_pcb = 0;
5921769Skarels 	rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family;
6021769Skarels 	rp->rcb_proto.sp_protocol = proto;
6121769Skarels 	insque(rp, &rawcb);
625635Sroot 	return (0);
635635Sroot bad2:
645635Sroot 	sbrelease(&so->so_snd);
655635Sroot bad:
665635Sroot 	(void) m_free(m);
675635Sroot 	return (ENOBUFS);
685635Sroot }
695635Sroot 
705635Sroot /*
715635Sroot  * Detach the raw connection block and discard
725635Sroot  * socket resources.
735635Sroot  */
745635Sroot raw_detach(rp)
755635Sroot 	register struct rawcb *rp;
765635Sroot {
775635Sroot 	struct socket *so = rp->rcb_socket;
785635Sroot 
79*24774Skarels 	if (rp->rcb_route.ro_rt)
80*24774Skarels 		rtfree(rp->rcb_route.ro_rt);
815635Sroot 	so->so_pcb = 0;
825635Sroot 	sofree(so);
835635Sroot 	remque(rp);
848975Sroot 	m_freem(dtom(rp));
855635Sroot }
865635Sroot 
875635Sroot /*
885635Sroot  * Disconnect and possibly release resources.
895635Sroot  */
905635Sroot raw_disconnect(rp)
915635Sroot 	struct rawcb *rp;
925635Sroot {
938975Sroot 
946509Ssam 	rp->rcb_flags &= ~RAW_FADDR;
957517Sroot 	if (rp->rcb_socket->so_state & SS_NOFDREF)
965635Sroot 		raw_detach(rp);
975635Sroot }
985635Sroot 
998394Swnj raw_bind(so, nam)
1008394Swnj 	register struct socket *so;
1018394Swnj 	struct mbuf *nam;
1028394Swnj {
1038394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
1048394Swnj 	register struct rawcb *rp;
1058394Swnj 
1068394Swnj 	if (ifnet == 0)
1078394Swnj 		return (EADDRNOTAVAIL);
1088394Swnj /* BEGIN DUBIOUS */
1098394Swnj 	/*
1108394Swnj 	 * Should we verify address not already in use?
1118394Swnj 	 * Some say yes, others no.
1128394Swnj 	 */
1138394Swnj 	switch (addr->sa_family) {
1148394Swnj 
115*24774Skarels #if defined(INET) || defined(BBNNET)
1168394Swnj 	case AF_IMPLINK:
11712783Ssam 	case AF_INET: {
1188394Swnj 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
11918409Skarels 		    ifa_ifwithaddr(addr) == 0)
1208394Swnj 			return (EADDRNOTAVAIL);
1218394Swnj 		break;
12212783Ssam 	}
12312783Ssam #endif
1248394Swnj 
1258394Swnj #ifdef PUP
1268394Swnj 	/*
1278394Swnj 	 * Curious, we convert PUP address format to internet
1288394Swnj 	 * to allow us to verify we're asking for an Ethernet
1298394Swnj 	 * interface.  This is wrong, but things are heavily
1308394Swnj 	 * oriented towards the internet addressing scheme, and
1318394Swnj 	 * converting internet to PUP would be very expensive.
1328394Swnj 	 */
1338394Swnj 	case AF_PUP: {
1348394Swnj 		struct sockaddr_pup *spup = (struct sockaddr_pup *)addr;
1358394Swnj 		struct sockaddr_in inpup;
1368394Swnj 
1379184Ssam 		bzero((caddr_t)&inpup, (unsigned)sizeof(inpup));
1388394Swnj 		inpup.sin_family = AF_INET;
13918409Skarels 		inpup.sin_addr = in_makeaddr(spup->spup_net, spup->spup_host);
1408394Swnj 		if (inpup.sin_addr.s_addr &&
14118409Skarels 		    ifa_ifwithaddr((struct sockaddr *)&inpup) == 0)
1428394Swnj 			return (EADDRNOTAVAIL);
1438394Swnj 		break;
1448394Swnj 	}
1458394Swnj #endif
1468394Swnj 
1478394Swnj 	default:
1488394Swnj 		return (EAFNOSUPPORT);
1498394Swnj 	}
1508394Swnj /* END DUBIOUS */
1519184Ssam 	rp = sotorawcb(so);
1528394Swnj 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr));
1538394Swnj 	rp->rcb_flags |= RAW_LADDR;
1548394Swnj 	return (0);
1558394Swnj }
1568394Swnj 
1575635Sroot /*
1585635Sroot  * Associate a peer's address with a
1595635Sroot  * raw connection block.
1605635Sroot  */
1618394Swnj raw_connaddr(rp, nam)
1625635Sroot 	struct rawcb *rp;
1638394Swnj 	struct mbuf *nam;
1645635Sroot {
1658394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
1668394Swnj 
1676509Ssam 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr));
1686509Ssam 	rp->rcb_flags |= RAW_FADDR;
1695635Sroot }
170