xref: /original-bsd/sys/net/raw_cb.c (revision 8a0cb482)
1 /*	raw_cb.c	4.5	82/03/13	*/
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 "../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  *	redo address binding to allow wildcards
22  */
23 
24 /*
25  * Allocate a control block and a nominal amount
26  * of buffer space for the socket.
27  */
28 raw_attach(so, addr)
29 	register struct socket *so;
30 	struct sockaddr *addr;
31 {
32 	struct mbuf *m;
33 	register struct rawcb *rp;
34 	struct ifnet *ifp = ifnet;
35 
36 COUNT(RAW_ATTACH);
37 	/*
38 	 * Should we verify address not already in use?
39 	 * Some say yes, others no.
40 	 */
41 	if (addr) switch (addr->sa_family) {
42 
43 	case AF_IMPLINK:
44 	case AF_INET: {
45 		register struct sockaddr_in *sin = (struct sockaddr_in *)addr;
46 
47 		if (ifnet && sin->sin_addr.s_addr == 0)
48 			sin->sin_addr = ifnet->if_addr;
49 		ifp = if_ifwithaddr(sin->sin_addr);
50 		break;
51 		}
52 
53 	case AF_PUP:
54 		ifp = ifnet;
55 		break;
56 
57 	default:
58 		return (EAFNOSUPPORT);
59 	}
60 	if (ifp == 0)
61 		return (EADDRNOTAVAIL);
62 	m = m_getclr(M_DONTWAIT);
63 	if (m == 0)
64 		return (ENOBUFS);
65 	if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
66 		goto bad;
67 	if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
68 		goto bad2;
69 	rp = mtod(m, struct rawcb *);
70 	rp->rcb_socket = so;
71 	insque(rp, &rawcb);
72 	so->so_pcb = (caddr_t)rp;
73 	rp->rcb_pcb = 0;
74 
75 	if (addr)
76 		bcopy((caddr_t)addr, (caddr_t)&so->so_addr, sizeof(*addr));
77 	return (0);
78 bad2:
79 	sbrelease(&so->so_snd);
80 bad:
81 	(void) m_free(m);
82 	return (ENOBUFS);
83 }
84 
85 /*
86  * Detach the raw connection block and discard
87  * socket resources.
88  */
89 raw_detach(rp)
90 	register struct rawcb *rp;
91 {
92 	struct socket *so = rp->rcb_socket;
93 
94 COUNT(RAW_DETACH);
95 	so->so_pcb = 0;
96 	sofree(so);
97 	remque(rp);
98 	m_freem(dtom(rp));
99 }
100 
101 /*
102  * Disconnect and possibly release resources.
103  */
104 raw_disconnect(rp)
105 	struct rawcb *rp;
106 {
107 COUNT(RAW_DISCONNECT);
108 	rp->rcb_flags &= ~RAW_ADDR;
109 	if (rp->rcb_socket->so_state & SS_USERGONE)
110 		raw_detach(rp);
111 }
112 
113 /*
114  * Associate a peer's address with a
115  * raw connection block.
116  */
117 raw_connaddr(rp, addr)
118 	struct rawcb *rp;
119 	struct sockaddr *addr;
120 {
121 COUNT(RAW_CONNADDR);
122 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_addr, sizeof(struct sockaddr));
123 	rp->rcb_flags |= RAW_ADDR;
124 }
125