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