xref: /csrg-svn/sys/net/raw_cb.c (revision 23160)
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.6 (Berkeley) 06/08/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 	so->so_pcb = 0;
80 	sofree(so);
81 	remque(rp);
82 	m_freem(dtom(rp));
83 }
84 
85 /*
86  * Disconnect and possibly release resources.
87  */
88 raw_disconnect(rp)
89 	struct rawcb *rp;
90 {
91 
92 	rp->rcb_flags &= ~RAW_FADDR;
93 	if (rp->rcb_socket->so_state & SS_NOFDREF)
94 		raw_detach(rp);
95 }
96 
97 raw_bind(so, nam)
98 	register struct socket *so;
99 	struct mbuf *nam;
100 {
101 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
102 	register struct rawcb *rp;
103 
104 	if (ifnet == 0)
105 		return (EADDRNOTAVAIL);
106 /* BEGIN DUBIOUS */
107 	/*
108 	 * Should we verify address not already in use?
109 	 * Some say yes, others no.
110 	 */
111 	switch (addr->sa_family) {
112 
113 #ifdef INET
114 	case AF_IMPLINK:
115 	case AF_INET: {
116 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
117 		    ifa_ifwithaddr(addr) == 0)
118 			return (EADDRNOTAVAIL);
119 		break;
120 	}
121 #endif
122 
123 #ifdef PUP
124 	/*
125 	 * Curious, we convert PUP address format to internet
126 	 * to allow us to verify we're asking for an Ethernet
127 	 * interface.  This is wrong, but things are heavily
128 	 * oriented towards the internet addressing scheme, and
129 	 * converting internet to PUP would be very expensive.
130 	 */
131 	case AF_PUP: {
132 		struct sockaddr_pup *spup = (struct sockaddr_pup *)addr;
133 		struct sockaddr_in inpup;
134 
135 		bzero((caddr_t)&inpup, (unsigned)sizeof(inpup));
136 		inpup.sin_family = AF_INET;
137 		inpup.sin_addr = in_makeaddr(spup->spup_net, spup->spup_host);
138 		if (inpup.sin_addr.s_addr &&
139 		    ifa_ifwithaddr((struct sockaddr *)&inpup) == 0)
140 			return (EADDRNOTAVAIL);
141 		break;
142 	}
143 #endif
144 
145 	default:
146 		return (EAFNOSUPPORT);
147 	}
148 /* END DUBIOUS */
149 	rp = sotorawcb(so);
150 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr));
151 	rp->rcb_flags |= RAW_LADDR;
152 	return (0);
153 }
154 
155 /*
156  * Associate a peer's address with a
157  * raw connection block.
158  */
159 raw_connaddr(rp, nam)
160 	struct rawcb *rp;
161 	struct mbuf *nam;
162 {
163 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
164 
165 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr));
166 	rp->rcb_flags |= RAW_FADDR;
167 }
168