xref: /csrg-svn/sys/net/raw_cb.c (revision 21769)
1 /*	raw_cb.c	6.5	85/06/02	*/
2 
3 #include "param.h"
4 #include "systm.h"
5 #include "mbuf.h"
6 #include "socket.h"
7 #include "socketvar.h"
8 #include "domain.h"
9 #include "protosw.h"
10 #include "errno.h"
11 
12 #include "if.h"
13 #include "route.h"
14 #include "raw_cb.h"
15 #include "../netinet/in.h"
16 #ifdef PUP
17 #include "../netpup/pup.h"
18 #endif
19 
20 #include "../vax/mtpr.h"
21 
22 /*
23  * Routines to manage the raw protocol control blocks.
24  *
25  * TODO:
26  *	hash lookups by protocol family/protocol + address family
27  *	take care of unique address problems per AF?
28  *	redo address binding to allow wildcards
29  */
30 
31 /*
32  * Allocate a control block and a nominal amount
33  * of buffer space for the socket.
34  */
35 raw_attach(so, proto)
36 	register struct socket *so;
37 	int proto;
38 {
39 	struct mbuf *m;
40 	register struct rawcb *rp;
41 
42 	m = m_getclr(M_DONTWAIT, MT_PCB);
43 	if (m == 0)
44 		return (ENOBUFS);
45 	if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
46 		goto bad;
47 	if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
48 		goto bad2;
49 	rp = mtod(m, struct rawcb *);
50 	rp->rcb_socket = so;
51 	so->so_pcb = (caddr_t)rp;
52 	rp->rcb_pcb = 0;
53 	rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family;
54 	rp->rcb_proto.sp_protocol = proto;
55 	insque(rp, &rawcb);
56 	return (0);
57 bad2:
58 	sbrelease(&so->so_snd);
59 bad:
60 	(void) m_free(m);
61 	return (ENOBUFS);
62 }
63 
64 /*
65  * Detach the raw connection block and discard
66  * socket resources.
67  */
68 raw_detach(rp)
69 	register struct rawcb *rp;
70 {
71 	struct socket *so = rp->rcb_socket;
72 
73 	so->so_pcb = 0;
74 	sofree(so);
75 	remque(rp);
76 	m_freem(dtom(rp));
77 }
78 
79 /*
80  * Disconnect and possibly release resources.
81  */
82 raw_disconnect(rp)
83 	struct rawcb *rp;
84 {
85 
86 	rp->rcb_flags &= ~RAW_FADDR;
87 	if (rp->rcb_socket->so_state & SS_NOFDREF)
88 		raw_detach(rp);
89 }
90 
91 raw_bind(so, nam)
92 	register struct socket *so;
93 	struct mbuf *nam;
94 {
95 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
96 	register struct rawcb *rp;
97 
98 	if (ifnet == 0)
99 		return (EADDRNOTAVAIL);
100 /* BEGIN DUBIOUS */
101 	/*
102 	 * Should we verify address not already in use?
103 	 * Some say yes, others no.
104 	 */
105 	switch (addr->sa_family) {
106 
107 #ifdef INET
108 	case AF_IMPLINK:
109 	case AF_INET: {
110 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
111 		    ifa_ifwithaddr(addr) == 0)
112 			return (EADDRNOTAVAIL);
113 		break;
114 	}
115 #endif
116 
117 #ifdef PUP
118 	/*
119 	 * Curious, we convert PUP address format to internet
120 	 * to allow us to verify we're asking for an Ethernet
121 	 * interface.  This is wrong, but things are heavily
122 	 * oriented towards the internet addressing scheme, and
123 	 * converting internet to PUP would be very expensive.
124 	 */
125 	case AF_PUP: {
126 		struct sockaddr_pup *spup = (struct sockaddr_pup *)addr;
127 		struct sockaddr_in inpup;
128 
129 		bzero((caddr_t)&inpup, (unsigned)sizeof(inpup));
130 		inpup.sin_family = AF_INET;
131 		inpup.sin_addr = in_makeaddr(spup->spup_net, spup->spup_host);
132 		if (inpup.sin_addr.s_addr &&
133 		    ifa_ifwithaddr((struct sockaddr *)&inpup) == 0)
134 			return (EADDRNOTAVAIL);
135 		break;
136 	}
137 #endif
138 
139 	default:
140 		return (EAFNOSUPPORT);
141 	}
142 /* END DUBIOUS */
143 	rp = sotorawcb(so);
144 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr));
145 	rp->rcb_flags |= RAW_LADDR;
146 	return (0);
147 }
148 
149 /*
150  * Associate a peer's address with a
151  * raw connection block.
152  */
153 raw_connaddr(rp, nam)
154 	struct rawcb *rp;
155 	struct mbuf *nam;
156 {
157 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
158 
159 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr));
160 	rp->rcb_flags |= RAW_FADDR;
161 }
162