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