1 /**************************************************************************/
2 /*                                                                        */
3 /*        HMP protocol: see RFC 869, Dec. 1983 for details                */
4 /*        original version by Craig Partridge (craig@bbn-unix)            */
5 /*                    January 1985                                        */
6 /*                                                                        */
7 /**************************************************************************/
8 
9 #ifdef HMP
10 
11 #include "../h/param.h"
12 #include "../h/dir.h"
13 #include "../h/user.h"
14 #include "../h/mbuf.h"
15 #include "../h/protosw.h"
16 #include "../h/socket.h"
17 #include "../h/socketvar.h"
18 #include "../h/errno.h"
19 
20 #include "../net/if.h"
21 #include "../net/route.h"
22 
23 #include "../bbnnet/in.h"
24 #include "../bbnnet/in_pcb.h"
25 #include "../bbnnet/in_var.h"
26 #include "../bbnnet/ip.h"
27 #include "../bbnnet/hmp.h"
28 #include "../bbnnet/hmp_var.h"
29 
30 extern hmp_binding_used();
31 
32 struct pr_advice hmp_advice =
33 {
34 	HM_MAXPORTS,
35 	HM_MAXPORTS,
36 	HM_MAXPORTS,
37 	HM_MAXPORTS,
38 	sizeof(u_char),
39 	hmp_binding_used,
40 } ;
41 
42 /**************************************************************************/
43 /*                                                                        */
44 /*   generate a new HMP inpcb                                             */
45 /*                                                                        */
46 /**************************************************************************/
47 
48 hmp_attach(so,head)
49 struct socket *so;
50 struct inpcb *head;
51 {
52     register struct inpcb *inp;
53     register struct mbuf *m;
54     register struct hmpcb *hp;
55     int error = 0;
56 
57     if (!(error = soreserve(so,2048,2048)))
58     {
59 	if (!(error = in_pcballoc(so,head)))
60 	{
61 	    inp = sotoinpcb(so);
62 	    inp->inp_lport = inp->inp_fport = 0;
63 
64 	    if ((m = m_getclr(M_WAIT,MT_PCB)) != (struct mbuf *)0)
65 	    {
66 		hp = mtod(m,struct hmpcb *);
67 		inp->inp_ppcb = (caddr_t) hp;
68 		return(0);
69 	    }
70 	    error = ENOBUFS;
71 	    in_pcbdetach(inp);
72 	}
73     }
74 
75     return(error);
76 }
77 
78 /**************************************************************************/
79 /*                                                                        */
80 /*    get rid of a no longer used HMP inpcb                               */
81 /*                                                                        */
82 /**************************************************************************/
83 
84 hmp_detach(inp)
85 register struct inpcb *inp;
86 {
87     register struct hmpcb *hp;
88     register int error;
89 
90     if (inp == (struct inpcb *)0)
91 	error = ENOTCONN;
92     else
93     {
94 	error = 0;
95 	hp = intohmpcb(inp);
96 	(void) m_free(dtom(hp));
97 	inp->inp_ppcb = (caddr_t)0;
98 
99 	in_pcbdetach(inp);
100     }
101     return(error);
102 }
103 
104 /**************************************************************************/
105 /*                                                                        */
106 /**************************************************************************/
107 
108 int hmp_binding_used(inp, lport, lsaddr, reuselocal)
109 struct inpcb   *inp;
110 u_short	lport;
111 u_long	lsaddr;
112 {
113     register struct inpcb *i;
114 
115     if (reuselocal)
116 	return(1);
117 
118     for (i = hmp.inp_next; i != &hmp; i = i->inp_next)
119     {
120 	/* don't want to find ourself */
121 	if ((i != inp) && (i->inp_lport == lport))
122 	    if ((i->inp_laddr.s_addr == lsaddr) ||
123 	    (i->inp_laddr.s_addr == INADDR_ANY) ||
124 	    (lsaddr == INADDR_ANY))
125 	    break;
126     }
127     return (i != &hmp);
128 }
129 
130 /**************************************************************************/
131 /*                                                                        */
132 /*     binds and stuffs all hmp garbage into its pcb                      */
133 /*                                                                        */
134 /**************************************************************************/
135 
136 hmp_bind(inp,nam)
137 struct inpcb *inp;
138 struct mbuf *nam;
139 {
140     int error;
141 
142     register struct hmpcb *hp = intohmpcb(inp);
143     register struct sockaddr_hmp *sinh;
144 
145     sinh = mtod(nam,struct sockaddr_hmp *);
146 
147     if (error = in_pcbbind(inp,nam,&hmp_advice))
148 	return(error);
149 
150     /* now do hmp stuff */
151 
152     hp->hp_inpcb = inp;
153     hp->hp_lsystyp = sinh->sih_systype;
154     hp->hp_lmsgtyp = sinh->sih_msgtype;
155     hp->hp_lseq = sinh->sih_seqno;
156     hp->hp_lpasswd = sinh->sih_passwd;
157     hp->hp_flags = sinh->sih_options & (HM_BINDOPTS);
158 
159     return(0);
160 }
161 
162 /**************************************************************************/
163 /*                                                                        */
164 /*   connect to remote end.  All this does is semi-permanently set the    */
165 /*   destination address.....                                             */
166 /*                                                                        */
167 /**************************************************************************/
168 
169 hmp_connect(inp,nam)
170 struct inpcb *inp;
171 struct mbuf *nam;
172 {
173     register struct socket *so = inp->inp_socket;
174     register struct sockaddr_hmp *sinh;
175     register struct hmpcb *hp;
176     register int error = 0;
177 
178     if (inp->inp_faddr.s_addr != INADDR_ANY)
179 	return(EISCONN);
180 
181     /* not bound? */
182     if (inp->inp_lport==0)
183     {
184         if (error = in_pcbbind(inp,(struct mbuf *)0),&hmp_advice)
185 	    return(error);
186     }
187 
188     if ((nam == (struct mbuf *)0) || (nam->m_len != sizeof(*sinh)))
189 	return(EINVAL);
190 
191     sinh = mtod(nam,struct sockaddr_hmp *);
192 
193     if ((sinh->sin_port & 0xff) != sinh->sin_port)
194 	return(EINVAL);
195 
196     inp->inp_fport = sinh->sin_port;
197     inp->inp_faddr = sinh->sin_addr;
198 
199     /* now do hmp stuff */
200 
201     hp = intohmpcb(inp);
202 
203     hp->hp_rsystyp = sinh->sih_systype;
204     hp->hp_rmsgtyp = sinh->sih_msgtype;
205     hp->hp_rseq = sinh->sih_seqno;
206     hp->hp_rpasswd = sinh->sih_passwd;
207     hp->hp_ctlflg = sinh->sih_ctlflgs;
208     hp->hp_flags = sinh->sih_options & HM_CONNOPTS;
209 
210     return(0);
211 }
212 
213 /**************************************************************************/
214 /*                                                                        */
215 /*     break association with a remote address                            */
216 /*                                                                        */
217 /**************************************************************************/
218 
219 hmp_disconnect(inp)
220 register struct inpcb *inp;
221 {
222     register struct hmpcb *hp;
223 
224     if (inp->inp_faddr.s_addr == INADDR_ANY)
225 	return(ENOTCONN);
226 
227     hp = intohmpcb(inp);
228 
229     /* clean up the hmpcb */
230 
231     hp->hp_rsystyp = 0;
232     hp->hp_rmsgtyp = 0;
233     hp->hp_rseq = 0;
234     hp->hp_rpasswd = 0;
235     hp->hp_ctlflg = 0;
236     hp->hp_flags &= ~HM_CONNOPTS;
237 
238     in_pcbdisconnect(inp);
239 
240     return(0);
241 }
242 #endif HMP
243