xref: /csrg-svn/sys/net/raw_cb.c (revision 26035)
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.9 (Berkeley) 02/02/86
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 	if (rp->rcb_options)
85 		m_freem(dtom(rp->rcb_options));
86 	m_freem(dtom(rp));
87 }
88 
89 /*
90  * Disconnect and possibly release resources.
91  */
92 raw_disconnect(rp)
93 	struct rawcb *rp;
94 {
95 
96 	rp->rcb_flags &= ~RAW_FADDR;
97 	if (rp->rcb_socket->so_state & SS_NOFDREF)
98 		raw_detach(rp);
99 }
100 
101 raw_bind(so, nam)
102 	register struct socket *so;
103 	struct mbuf *nam;
104 {
105 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
106 	register struct rawcb *rp;
107 
108 	if (ifnet == 0)
109 		return (EADDRNOTAVAIL);
110 /* BEGIN DUBIOUS */
111 	/*
112 	 * Should we verify address not already in use?
113 	 * Some say yes, others no.
114 	 */
115 	switch (addr->sa_family) {
116 
117 #ifdef INET
118 	case AF_IMPLINK:
119 	case AF_INET: {
120 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
121 		    ifa_ifwithaddr(addr) == 0)
122 			return (EADDRNOTAVAIL);
123 		break;
124 	}
125 #endif
126 
127 	default:
128 		return (EAFNOSUPPORT);
129 	}
130 /* END DUBIOUS */
131 	rp = sotorawcb(so);
132 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr));
133 	rp->rcb_flags |= RAW_LADDR;
134 	return (0);
135 }
136 
137 /*
138  * Associate a peer's address with a
139  * raw connection block.
140  */
141 raw_connaddr(rp, nam)
142 	struct rawcb *rp;
143 	struct mbuf *nam;
144 {
145 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
146 
147 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr));
148 	rp->rcb_flags |= RAW_FADDR;
149 }
150