xref: /csrg-svn/sys/net/raw_cb.c (revision 5772)
1 /*	raw_cb.c	4.3	82/02/12	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/mbuf.h"
6 #include "../h/socket.h"
7 #include "../h/socketvar.h"
8 #include "../h/mtpr.h"
9 #include "../net/in.h"
10 #include "../net/in_systm.h"
11 #include "../net/if.h"
12 #include "../net/raw_cb.h"
13 #include "/usr/include/errno.h"
14 
15 /*
16  * Routines to manage the raw protocol control blocks.
17  *
18  * TODO:
19  *	hash lookups by protocol family/protocol + address family
20  *	take care of unique address problems per AF
21  */
22 
23 /*
24  * Allocate a control block and a nominal amount
25  * of buffer space for the socket.
26  */
27 raw_attach(so, addr)
28 	register struct socket *so;
29 	struct sockaddr *addr;
30 {
31 	struct mbuf *m;
32 	register struct rawcb *rp;
33 	struct ifnet *ifp = ifnet;
34 
35 COUNT(RAW_ATTACH);
36 	/*
37 	 * Should we verify address not already in use?
38 	 * Some say yes, others no.
39 	 */
40 	if (addr) switch (addr->sa_family) {
41 
42 	case AF_IMPLINK:
43 	case AF_INET: {
44 		register struct sockaddr_in *sin = (struct sockaddr_in *)addr;
45 
46 		if (ifnet && sin->sin_addr.s_addr == 0)
47 			sin->sin_addr = ifnet->if_addr;
48 		ifp = if_ifwithaddr(sin->sin_addr);
49 		break;
50 		}
51 
52 	default:
53 		return (EAFNOSUPPORT);
54 	}
55 	if (ifp == 0)
56 		return (EADDRNOTAVAIL);
57 	m = m_getclr(M_DONTWAIT);
58 	if (m == 0)
59 		return (ENOBUFS);
60 	if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
61 		goto bad;
62 	if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
63 		goto bad2;
64 	rp = mtod(m, struct rawcb *);
65 	rp->rcb_socket = so;
66 	insque(rp, &rawcb);
67 	so->so_pcb = (caddr_t)rp;
68 	rp->rcb_pcb = 0;
69 
70 	if (addr)
71 		bcopy(addr, &so->so_addr, sizeof(*addr));
72 	return (0);
73 bad2:
74 	sbrelease(&so->so_snd);
75 bad:
76 	(void) m_free(m);
77 	return (ENOBUFS);
78 }
79 
80 /*
81  * Detach the raw connection block and discard
82  * socket resources.
83  */
84 raw_detach(rp)
85 	register struct rawcb *rp;
86 {
87 	struct socket *so = rp->rcb_socket;
88 
89 COUNT(RAW_DETACH);
90 	so->so_pcb = 0;
91 	sofree(so);
92 	remque(rp);
93 	(void) m_freem(dtom(rp));
94 }
95 
96 /*
97  * Disconnect and possibly release resources.
98  */
99 raw_disconnect(rp)
100 	struct rawcb *rp;
101 {
102 COUNT(RAW_DISCONNECT);
103 	rp->rcb_flags &= ~RAW_ADDR;
104 	if (rp->rcb_socket->so_state & SS_USERGONE)
105 		raw_detach(rp);
106 }
107 
108 /*
109  * Associate a peer's address with a
110  * raw connection block.
111  */
112 raw_connaddr(rp, addr)
113 	struct rawcb *rp;
114 	struct sockaddr *addr;
115 {
116 COUNT(RAW_CONNADDR);
117 	bcopy(addr, &rp->rcb_addr, sizeof(struct sockaddr));
118 	rp->rcb_flags |= RAW_ADDR;
119 }
120