xref: /original-bsd/sys/net/raw_cb.c (revision cd18b70b)
1 /*
2  * Copyright (c) 1980, 1986 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	7.3 (Berkeley) 10/28/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 
23 #include "../machine/mtpr.h"
24 
25 /*
26  * Routines to manage the raw protocol control blocks.
27  *
28  * TODO:
29  *	hash lookups by protocol family/protocol + address family
30  *	take care of unique address problems per AF?
31  *	redo address binding to allow wildcards
32  */
33 
34 /*
35  * Allocate a control block and a nominal amount
36  * of buffer space for the socket.
37  */
38 raw_attach(so, proto)
39 	register struct socket *so;
40 	int proto;
41 {
42 	struct mbuf *m;
43 	register struct rawcb *rp;
44 
45 	m = m_getclr(M_DONTWAIT, MT_PCB);
46 	if (m == 0)
47 		return (ENOBUFS);
48 	if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
49 		goto bad;
50 	if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
51 		goto bad2;
52 	rp = mtod(m, struct rawcb *);
53 	rp->rcb_socket = so;
54 	so->so_pcb = (caddr_t)rp;
55 	rp->rcb_pcb = 0;
56 	rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family;
57 	rp->rcb_proto.sp_protocol = proto;
58 	insque(rp, &rawcb);
59 	return (0);
60 bad2:
61 	sbrelease(&so->so_snd);
62 bad:
63 	(void) m_free(m);
64 	return (ENOBUFS);
65 }
66 
67 /*
68  * Detach the raw connection block and discard
69  * socket resources.
70  */
71 raw_detach(rp)
72 	register struct rawcb *rp;
73 {
74 	struct socket *so = rp->rcb_socket;
75 
76 	if (rp->rcb_route.ro_rt)
77 		rtfree(rp->rcb_route.ro_rt);
78 	so->so_pcb = 0;
79 	sofree(so);
80 	remque(rp);
81 	if (rp->rcb_options)
82 		m_freem(rp->rcb_options);
83 	m_freem(dtom(rp));
84 }
85 
86 /*
87  * Disconnect and possibly release resources.
88  */
89 raw_disconnect(rp)
90 	struct rawcb *rp;
91 {
92 
93 	rp->rcb_flags &= ~RAW_FADDR;
94 	if (rp->rcb_socket->so_state & SS_NOFDREF)
95 		raw_detach(rp);
96 }
97 
98 raw_bind(so, nam)
99 	register struct socket *so;
100 	struct mbuf *nam;
101 {
102 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
103 	register struct rawcb *rp;
104 
105 	if (ifnet == 0)
106 		return (EADDRNOTAVAIL);
107 /* BEGIN DUBIOUS */
108 	/*
109 	 * Should we verify address not already in use?
110 	 * Some say yes, others no.
111 	 */
112 	switch (addr->sa_family) {
113 
114 #ifdef INET
115 	case AF_IMPLINK:
116 	case AF_INET: {
117 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
118 		    ifa_ifwithaddr(addr) == 0)
119 			return (EADDRNOTAVAIL);
120 		break;
121 	}
122 #endif
123 
124 	default:
125 		return (EAFNOSUPPORT);
126 	}
127 /* END DUBIOUS */
128 	rp = sotorawcb(so);
129 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr));
130 	rp->rcb_flags |= RAW_LADDR;
131 	return (0);
132 }
133 
134 /*
135  * Associate a peer's address with a
136  * raw connection block.
137  */
138 raw_connaddr(rp, nam)
139 	struct rawcb *rp;
140 	struct mbuf *nam;
141 {
142 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
143 
144 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr));
145 	rp->rcb_flags |= RAW_FADDR;
146 }
147