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