xref: /csrg-svn/sys/net/raw_cb.c (revision 36823)
1 /*
2  * Copyright (c) 1980, 1986 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)raw_cb.c	7.7 (Berkeley) 02/17/89
18  */
19 
20 #include "param.h"
21 #include "systm.h"
22 #include "mbuf.h"
23 #include "socket.h"
24 #include "socketvar.h"
25 #include "domain.h"
26 #include "protosw.h"
27 #include "errno.h"
28 
29 #include "if.h"
30 #include "route.h"
31 #include "raw_cb.h"
32 #include "../netinet/in.h"
33 
34 #include "../machine/mtpr.h"
35 
36 /*
37  * Routines to manage the raw protocol control blocks.
38  *
39  * TODO:
40  *	hash lookups by protocol family/protocol + address family
41  *	take care of unique address problems per AF?
42  *	redo address binding to allow wildcards
43  */
44 
45 u_long	raw_sendspace = RAWSNDQ;
46 u_long	raw_recvspace = RAWRCVQ;
47 
48 /*
49  * Allocate a control block and a nominal amount
50  * of buffer space for the socket.
51  */
52 raw_attach(so, proto)
53 	register struct socket *so;
54 	int proto;
55 {
56 	struct mbuf *m;
57 	register struct rawcb *rp;
58 
59 	m = m_getclr(M_DONTWAIT, MT_PCB);
60 	if (m == 0)
61 		return (ENOBUFS);
62 	if (sbreserve(&so->so_snd, raw_sendspace) == 0)
63 		goto bad;
64 	if (sbreserve(&so->so_rcv, raw_recvspace) == 0)
65 		goto bad2;
66 	rp = mtod(m, struct rawcb *);
67 	rp->rcb_socket = so;
68 	so->so_pcb = (caddr_t)rp;
69 	rp->rcb_pcb = 0;
70 	rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family;
71 	rp->rcb_proto.sp_protocol = proto;
72 	insque(rp, &rawcb);
73 	return (0);
74 bad2:
75 	sbrelease(&so->so_snd);
76 bad:
77 	(void) m_free(m);
78 	return (ENOBUFS);
79 }
80 
81 /*
82  * Detach the raw connection block and discard
83  * socket resources.
84  */
85 raw_detach(rp)
86 	register struct rawcb *rp;
87 {
88 	struct socket *so = rp->rcb_socket;
89 
90 	if (rp->rcb_route.ro_rt)
91 		rtfree(rp->rcb_route.ro_rt);
92 	so->so_pcb = 0;
93 	sofree(so);
94 	remque(rp);
95 	if (rp->rcb_options)
96 		m_freem(rp->rcb_options);
97 	m_freem(dtom(rp));
98 }
99 
100 /*
101  * Disconnect and possibly release resources.
102  */
103 raw_disconnect(rp)
104 	struct rawcb *rp;
105 {
106 
107 	rp->rcb_flags &= ~RAW_FADDR;
108 	if (rp->rcb_socket->so_state & SS_NOFDREF)
109 		raw_detach(rp);
110 }
111 
112 raw_bind(so, nam)
113 	register struct socket *so;
114 	struct mbuf *nam;
115 {
116 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
117 	register struct rawcb *rp;
118 
119 	if (ifnet == 0)
120 		return (EADDRNOTAVAIL);
121 /* BEGIN DUBIOUS */
122 	/*
123 	 * Should we verify address not already in use?
124 	 * Some say yes, others no.
125 	 */
126 	switch (addr->sa_family) {
127 
128 #ifdef INET
129 	case AF_IMPLINK:
130 	case AF_INET: {
131 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
132 		    ifa_ifwithaddr(addr) == 0)
133 			return (EADDRNOTAVAIL);
134 		break;
135 	}
136 #endif
137 
138 	default:
139 		return (EAFNOSUPPORT);
140 	}
141 /* END DUBIOUS */
142 	rp = sotorawcb(so);
143 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr));
144 	rp->rcb_flags |= RAW_LADDR;
145 	return (0);
146 }
147 
148 /*
149  * Associate a peer's address with a
150  * raw connection block.
151  */
152 raw_connaddr(rp, nam)
153 	struct rawcb *rp;
154 	struct mbuf *nam;
155 {
156 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
157 
158 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr));
159 	rp->rcb_flags |= RAW_FADDR;
160 }
161