xref: /original-bsd/sys/net/raw_cb.c (revision fbed46ce)
1 /*	raw_cb.c	4.8	82/04/11	*/
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 "../net/pup.h"
14 #include "../errno.h"
15 
16 /*
17  * Routines to manage the raw protocol control blocks.
18  *
19  * TODO:
20  *	hash lookups by protocol family/protocol + address family
21  *	take care of unique address problems per AF?
22  *	redo address binding to allow wildcards
23  */
24 
25 /*
26  * Allocate a control block and a nominal amount
27  * of buffer space for the socket.
28  */
29 raw_attach(so, addr)
30 	register struct socket *so;
31 	struct sockaddr *addr;
32 {
33 	struct mbuf *m;
34 	register struct rawcb *rp;
35 
36 COUNT(RAW_ATTACH);
37 	if (ifnet == 0)
38 		return (EADDRNOTAVAIL);
39 	/*
40 	 * Should we verify address not already in use?
41 	 * Some say yes, others no.
42 	 */
43 	if (addr) switch (addr->sa_family) {
44 
45 	case AF_IMPLINK:
46 	case AF_INET:
47 		if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
48 		    if_ifwithaddr(addr) == 0)
49 			return (EADDRNOTAVAIL);
50 		break;
51 
52 #ifdef PUP
53 	/*
54 	 * Curious, we convert PUP address format to internet
55 	 * to allow us to verify we're asking for an Ethernet
56 	 * interface.  This is wrong, but things are heavily
57 	 * oriented towards the internet addressing scheme, and
58 	 * converting internet to PUP would be very expensive.
59 	 */
60 	case AF_PUP: {
61 		struct sockaddr_pup *spup = (struct sockaddr_pup *)addr;
62 		struct sockaddr_in inpup;
63 
64 		bzero((caddr_t)&inpup, sizeof(inpup));
65 		inpup.sin_family = AF_INET;
66 		inpup.sin_addr.s_net = spup->sp_net;
67 		inpup.sin_addr.s_impno = spup->sp_host;
68 		if (inpup.sin_addr.s_addr &&
69 		    if_ifwithaddr((struct sockaddr *)&inpup) == 0)
70 			return (EADDRNOTAVAIL);
71 		break;
72 	}
73 #endif
74 
75 	default:
76 		return (EAFNOSUPPORT);
77 	}
78 	m = m_getclr(M_DONTWAIT);
79 	if (m == 0)
80 		return (ENOBUFS);
81 	if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
82 		goto bad;
83 	if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
84 		goto bad2;
85 	rp = mtod(m, struct rawcb *);
86 	rp->rcb_socket = so;
87 	insque(rp, &rawcb);
88 	so->so_pcb = (caddr_t)rp;
89 	rp->rcb_pcb = 0;
90 	if (addr) {
91 		bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof(*addr));
92 		rp->rcb_flags |= RAW_LADDR;
93 	}
94 	return (0);
95 bad2:
96 	sbrelease(&so->so_snd);
97 bad:
98 	(void) m_free(m);
99 	return (ENOBUFS);
100 }
101 
102 /*
103  * Detach the raw connection block and discard
104  * socket resources.
105  */
106 raw_detach(rp)
107 	register struct rawcb *rp;
108 {
109 	struct socket *so = rp->rcb_socket;
110 
111 COUNT(RAW_DETACH);
112 	so->so_pcb = 0;
113 	sofree(so);
114 	remque(rp);
115 	(void) m_freem(dtom(rp));
116 }
117 
118 /*
119  * Disconnect and possibly release resources.
120  */
121 raw_disconnect(rp)
122 	struct rawcb *rp;
123 {
124 COUNT(RAW_DISCONNECT);
125 	rp->rcb_flags &= ~RAW_FADDR;
126 	if (rp->rcb_socket->so_state & SS_USERGONE)
127 		raw_detach(rp);
128 }
129 
130 /*
131  * Associate a peer's address with a
132  * raw connection block.
133  */
134 raw_connaddr(rp, addr)
135 	struct rawcb *rp;
136 	struct sockaddr *addr;
137 {
138 COUNT(RAW_CONNADDR);
139 	bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr));
140 	rp->rcb_flags |= RAW_FADDR;
141 }
142