xref: /csrg-svn/sys/net/raw_cb.c (revision 8394)
1*8394Swnj /*	raw_cb.c	4.12	82/10/09	*/
25635Sroot 
35635Sroot #include "../h/param.h"
45635Sroot #include "../h/systm.h"
55635Sroot #include "../h/mbuf.h"
65635Sroot #include "../h/socket.h"
75635Sroot #include "../h/socketvar.h"
85635Sroot #include "../h/mtpr.h"
95635Sroot #include "../net/if.h"
105635Sroot #include "../net/raw_cb.h"
117298Ssam #include <errno.h>
125635Sroot 
135635Sroot /*
145635Sroot  * Routines to manage the raw protocol control blocks.
155635Sroot  *
165635Sroot  * TODO:
175635Sroot  *	hash lookups by protocol family/protocol + address family
186339Ssam  *	take care of unique address problems per AF?
196045Swnj  *	redo address binding to allow wildcards
205635Sroot  */
215635Sroot 
225635Sroot /*
235635Sroot  * Allocate a control block and a nominal amount
245635Sroot  * of buffer space for the socket.
255635Sroot  */
26*8394Swnj raw_attach(so)
275635Sroot 	register struct socket *so;
285635Sroot {
295635Sroot 	struct mbuf *m;
305635Sroot 	register struct rawcb *rp;
315635Sroot 
325635Sroot 	m = m_getclr(M_DONTWAIT);
335635Sroot 	if (m == 0)
345635Sroot 		return (ENOBUFS);
355635Sroot 	if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
365635Sroot 		goto bad;
375635Sroot 	if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
385635Sroot 		goto bad2;
395635Sroot 	rp = mtod(m, struct rawcb *);
405635Sroot 	rp->rcb_socket = so;
415635Sroot 	insque(rp, &rawcb);
425635Sroot 	so->so_pcb = (caddr_t)rp;
435635Sroot 	rp->rcb_pcb = 0;
445635Sroot 	return (0);
455635Sroot bad2:
465635Sroot 	sbrelease(&so->so_snd);
475635Sroot bad:
485635Sroot 	(void) m_free(m);
495635Sroot 	return (ENOBUFS);
505635Sroot }
515635Sroot 
525635Sroot /*
535635Sroot  * Detach the raw connection block and discard
545635Sroot  * socket resources.
555635Sroot  */
565635Sroot raw_detach(rp)
575635Sroot 	register struct rawcb *rp;
585635Sroot {
595635Sroot 	struct socket *so = rp->rcb_socket;
605635Sroot 
615635Sroot 	so->so_pcb = 0;
625635Sroot 	sofree(so);
635635Sroot 	remque(rp);
646339Ssam 	(void) m_freem(dtom(rp));
655635Sroot }
665635Sroot 
675635Sroot /*
685635Sroot  * Disconnect and possibly release resources.
695635Sroot  */
705635Sroot raw_disconnect(rp)
715635Sroot 	struct rawcb *rp;
725635Sroot {
736509Ssam 	rp->rcb_flags &= ~RAW_FADDR;
747517Sroot 	if (rp->rcb_socket->so_state & SS_NOFDREF)
755635Sroot 		raw_detach(rp);
765635Sroot }
775635Sroot 
78*8394Swnj raw_bind(so, nam)
79*8394Swnj 	register struct socket *so;
80*8394Swnj 	struct mbuf *nam;
81*8394Swnj {
82*8394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
83*8394Swnj 	struct mbuf *m;
84*8394Swnj 	register struct rawcb *rp;
85*8394Swnj 
86*8394Swnj 	if (ifnet == 0)
87*8394Swnj 		return (EADDRNOTAVAIL);
88*8394Swnj {
89*8394Swnj #include "../netinet/in.h"
90*8394Swnj #include "../netinet/in_systm.h"
91*8394Swnj /* BEGIN DUBIOUS */
92*8394Swnj 	/*
93*8394Swnj 	 * Should we verify address not already in use?
94*8394Swnj 	 * Some say yes, others no.
95*8394Swnj 	 */
96*8394Swnj 	switch (addr->sa_family) {
97*8394Swnj 
98*8394Swnj 	case AF_IMPLINK:
99*8394Swnj 	case AF_INET:
100*8394Swnj 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
101*8394Swnj 		    if_ifwithaddr(addr) == 0)
102*8394Swnj 			return (EADDRNOTAVAIL);
103*8394Swnj 		break;
104*8394Swnj 
105*8394Swnj #ifdef PUP
106*8394Swnj 	/*
107*8394Swnj 	 * Curious, we convert PUP address format to internet
108*8394Swnj 	 * to allow us to verify we're asking for an Ethernet
109*8394Swnj 	 * interface.  This is wrong, but things are heavily
110*8394Swnj 	 * oriented towards the internet addressing scheme, and
111*8394Swnj 	 * converting internet to PUP would be very expensive.
112*8394Swnj 	 */
113*8394Swnj 	case AF_PUP: {
114*8394Swnj #include "../netpup/pup.h"
115*8394Swnj 		struct sockaddr_pup *spup = (struct sockaddr_pup *)addr;
116*8394Swnj 		struct sockaddr_in inpup;
117*8394Swnj 
118*8394Swnj 		bzero((caddr_t)&inpup, sizeof(inpup));
119*8394Swnj 		inpup.sin_family = AF_INET;
120*8394Swnj 		inpup.sin_addr.s_net = spup->sp_net;
121*8394Swnj 		inpup.sin_addr.s_impno = spup->sp_host;
122*8394Swnj 		if (inpup.sin_addr.s_addr &&
123*8394Swnj 		    if_ifwithaddr((struct sockaddr *)&inpup) == 0)
124*8394Swnj 			return (EADDRNOTAVAIL);
125*8394Swnj 		break;
126*8394Swnj 	}
127*8394Swnj #endif
128*8394Swnj 
129*8394Swnj 	default:
130*8394Swnj 		return (EAFNOSUPPORT);
131*8394Swnj 	}
132*8394Swnj }
133*8394Swnj /* END DUBIOUS */
134*8394Swnj 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr));
135*8394Swnj 	rp->rcb_flags |= RAW_LADDR;
136*8394Swnj 	return (0);
137*8394Swnj }
138*8394Swnj 
1395635Sroot /*
1405635Sroot  * Associate a peer's address with a
1415635Sroot  * raw connection block.
1425635Sroot  */
143*8394Swnj raw_connaddr(rp, nam)
1445635Sroot 	struct rawcb *rp;
145*8394Swnj 	struct mbuf *nam;
1465635Sroot {
147*8394Swnj 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
148*8394Swnj 
1496509Ssam 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr));
1506509Ssam 	rp->rcb_flags |= RAW_FADDR;
1515635Sroot }
152