xref: /original-bsd/sys/net/raw_cb.c (revision 2301fdfb)
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.6 (Berkeley) 06/27/88
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 /*
46  * Allocate a control block and a nominal amount
47  * of buffer space for the socket.
48  */
49 raw_attach(so, proto)
50 	register struct socket *so;
51 	int proto;
52 {
53 	struct mbuf *m;
54 	register struct rawcb *rp;
55 
56 	m = m_getclr(M_DONTWAIT, MT_PCB);
57 	if (m == 0)
58 		return (ENOBUFS);
59 	if (sbreserve(&so->so_snd, (u_long) RAWSNDQ) == 0)
60 		goto bad;
61 	if (sbreserve(&so->so_rcv, (u_long) RAWRCVQ) == 0)
62 		goto bad2;
63 	rp = mtod(m, struct rawcb *);
64 	rp->rcb_socket = so;
65 	so->so_pcb = (caddr_t)rp;
66 	rp->rcb_pcb = 0;
67 	rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family;
68 	rp->rcb_proto.sp_protocol = proto;
69 	insque(rp, &rawcb);
70 	return (0);
71 bad2:
72 	sbrelease(&so->so_snd);
73 bad:
74 	(void) m_free(m);
75 	return (ENOBUFS);
76 }
77 
78 /*
79  * Detach the raw connection block and discard
80  * socket resources.
81  */
82 raw_detach(rp)
83 	register struct rawcb *rp;
84 {
85 	struct socket *so = rp->rcb_socket;
86 
87 	if (rp->rcb_route.ro_rt)
88 		rtfree(rp->rcb_route.ro_rt);
89 	so->so_pcb = 0;
90 	sofree(so);
91 	remque(rp);
92 	if (rp->rcb_options)
93 		m_freem(rp->rcb_options);
94 	m_freem(dtom(rp));
95 }
96 
97 /*
98  * Disconnect and possibly release resources.
99  */
100 raw_disconnect(rp)
101 	struct rawcb *rp;
102 {
103 
104 	rp->rcb_flags &= ~RAW_FADDR;
105 	if (rp->rcb_socket->so_state & SS_NOFDREF)
106 		raw_detach(rp);
107 }
108 
109 raw_bind(so, nam)
110 	register struct socket *so;
111 	struct mbuf *nam;
112 {
113 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
114 	register struct rawcb *rp;
115 
116 	if (ifnet == 0)
117 		return (EADDRNOTAVAIL);
118 /* BEGIN DUBIOUS */
119 	/*
120 	 * Should we verify address not already in use?
121 	 * Some say yes, others no.
122 	 */
123 	switch (addr->sa_family) {
124 
125 #ifdef INET
126 	case AF_IMPLINK:
127 	case AF_INET: {
128 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
129 		    ifa_ifwithaddr(addr) == 0)
130 			return (EADDRNOTAVAIL);
131 		break;
132 	}
133 #endif
134 
135 	default:
136 		return (EAFNOSUPPORT);
137 	}
138 /* END DUBIOUS */
139 	rp = sotorawcb(so);
140 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr));
141 	rp->rcb_flags |= RAW_LADDR;
142 	return (0);
143 }
144 
145 /*
146  * Associate a peer's address with a
147  * raw connection block.
148  */
149 raw_connaddr(rp, nam)
150 	struct rawcb *rp;
151 	struct mbuf *nam;
152 {
153 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
154 
155 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr));
156 	rp->rcb_flags |= RAW_FADDR;
157 }
158