1 /**************************************************************************/
2 /* */
3 /* HMP protocol: see RFC 869, Dec. 1983 for details */
4 /* */
5 /* users are warned that this code has not been extensively tested: */
6 /* it was written for use on SUNs in Jan of 1985, by Craig Partridge */
7 /* and has been used a bit by some by local projects. It was ported */
8 /* to 4.3 to replace some HMP code that had what now goes into a user */
9 /* level server process in the kernel. This has not been */
10 /* heavily tested. Think of this as alpha test code... */
11 /* */
12 /**************************************************************************/
13
14 #ifdef HMP
15
16 #include "../h/param.h"
17 #include "../h/dir.h"
18 #include "../h/user.h"
19 #include "../h/mbuf.h"
20 #include "../h/protosw.h"
21 #include "../h/socket.h"
22 #include "../h/socketvar.h"
23 #include "../h/errno.h"
24
25 #include "../net/if.h"
26 #include "../net/route.h"
27
28 #include "../bbnnet/in.h"
29 #include "../bbnnet/in_pcb.h"
30 #include "../bbnnet/in_var.h"
31 #include "../bbnnet/ip.h"
32 #include "../bbnnet/hmp.h"
33 #include "../bbnnet/hmp_var.h"
34
35 /* hmp pcb queue */
36 struct inpcb hmp;
37
38 /**************************************************************************/
39 /* */
40 /* called to initialize hmp control structures */
41 /* */
42 /**************************************************************************/
43
hmp_init()44 hmp_init()
45 {
46 hmp.inp_next = hmp.inp_prev = &hmp;
47 }
48
49 /**************************************************************************/
50 /* */
51 /* called to handle input packet by IP level. Does checksum, finds if */
52 /* destination port exists and does any screening if port was bound by */
53 /* application. Note that it also re-routes poll requests to HOST_PORT */
54 /* */
55 /**************************************************************************/
56
57 hmp_input(m0)
58 struct mbuf *m0;
59 {
60 struct ip *ih;
61 struct mbuf *m;
62 struct hmp_hdr *hh;
63 struct hmpcb *hp;
64 struct inpcb *inp;
65 struct in_addr dst, src;
66 u_short sav_cksum, port;
67 int len;
68 static struct sockaddr_hmp hmp_hmp;
69
70 /* grab header */
71 m = m0;
72 if (((m->m_off > MMAXOFF) || (m->m_len < HMPIPHDR)) &&
73 (m = m_pullup(m,HMPIPHDR)) == (struct mbuf *)0)
74 return;
75
76 ih = mtod(m,struct ip *);
77
78 /* save what we need from IP header */
79 dst = ih->ip_dst;
80 src = ih->ip_src;
81
82 len = ih->ip_len;
83
84 /* get rid of IP header */
85 m->m_len -= sizeof(struct ip);
86 m->m_off += sizeof(struct ip);
87 len -= sizeof(struct ip);
88
89 hh = mtod(m,struct hmp_hdr *);
90
91 /* do checksum */
92 sav_cksum = hh->hh_cksum;
93 hh->hh_cksum = 0;
94 if (sav_cksum != in_cksum(m,len))
95 goto bad;
96
97 /* are we being polled ?*/
98 if (hh->hh_msgtyp == HM_POLL)
99 port = HOST_PORT;
100 else
101 port = hh->hh_port;
102
103 /* find associated pcb if any */
104 inp = in_pcblookup(&hmp,ih->ip_src,(u_short)0, dst, port,1);
105
106 if (inp == (struct inpcb *)0)
107 {
108 goto bad;
109 }
110
111 hp = intohmpcb(inp);
112
113 /* is this packet of a type we accept? */
114
115 if (port == HOST_PORT)
116 {
117 /* check system type and password */
118
119 if ((hp->hp_lsystyp) && (hh->hh_systyp != hp->hp_lsystyp))
120 goto bad;
121
122 if ((hp->hp_lpasswd) && (hh->hh_passwd != hp->hp_lpasswd))
123 goto bad;
124
125 }
126 else if ((hp->hp_flags & HM_SEQOPT) && (hh->hh_passwd != hp->hp_lseq))
127 goto bad; /* out of sequence */
128
129 hp->hp_lseq = htons(ntohs(hp->hp_lseq)+1);
130
131 /* censoring message types? */
132 /* also see if letting traps thru */
133
134 if ((hp->hp_lmsgtyp) && (hh->hh_msgtyp != hp->hp_lmsgtyp) &&
135 (!(hp->hp_flags & HM_TRAPOPT) || (hh->hh_msgtyp != HM_TRAP)))
136 goto bad;
137
138 /* construct sockaddr_hmp */
139
140 hmp_hmp.sin_port = hh->hh_port;
141 hmp_hmp.sin_addr = src;
142 hmp_hmp.sih_seqno = hh->hh_seq;
143 hmp_hmp.sih_passwd = hh->hh_passwd;
144 hmp_hmp.sih_systype = hh->hh_systyp;
145 hmp_hmp.sih_msgtype = hh->hh_msgtyp;
146 hmp_hmp.sih_ctlflgs = hh->hh_ctlflg;
147 hmp_hmp.sih_options = 0;
148
149 /* drop HMP header */
150 m->m_len -= sizeof(struct hmp_hdr);
151 m->m_off += sizeof(struct hmp_hdr);
152
153 if (sbappendaddr(&inp->inp_socket->so_rcv,(struct sockaddr *)&hmp_hmp,
154 m, (struct mbuf *)0) == 0)
155 goto bad;
156 else
157 sorwakeup(inp->inp_socket);
158 return;
159
160 bad :
161 m_freem(m);
162 }
163
164 /**************************************************************************/
165 /* */
166 /* sends packet. Checks for some wild values and does some magic if */
167 /* the sender is the HOST_PORT. */
168 /* */
169 /**************************************************************************/
170
hmp_output(inp,m0)171 hmp_output(inp, m0)
172 register struct inpcb *inp;
173 struct mbuf *m0;
174 {
175 register struct mbuf *m;
176 register struct hmp_hdr *hh;
177 register struct ip *ip;
178 register struct hmpcb *hp = intohmpcb(inp);
179 int len, error;
180
181 /* check for wild message types */
182
183 if ((hp->hp_rmsgtyp <=0) || (hp->hp_rmsgtyp > 102) ||
184 ((hp->hp_rmsgtyp > 7) && (hp->hp_rmsgtyp < 100)))
185 {
186 m = m0;
187 error = EINVAL;
188 goto dropit;
189 }
190
191 /* compute length and grab mbuf for HMP/IP header */
192 for(m=m0,len=0; m != (struct mbuf *)0; m = m->m_next)
193 len += m->m_len;
194
195 if ((m = m_get(M_DONTWAIT,MT_HEADER)) == (struct mbuf *)0)
196 {
197 m = m0;
198 error = ENOBUFS;
199 goto dropit;
200 }
201
202 /* do HMP header */
203 m->m_off = MMAXOFF - sizeof(struct hmp_hdr);
204 m->m_len = sizeof(struct hmp_hdr);
205 m->m_next = m0;
206
207 hh = mtod(m,struct hmp_hdr *);
208
209 /* traps and responding to polls we are host sending to appl */
210 if ((inp->inp_lport == HOST_PORT) || (hp->hp_rmsgtyp == HM_TRAP))
211 {
212 hh->hh_systyp = hp->hp_lsystyp;
213 hh->hh_port = (u_char) inp->inp_fport;
214 }
215 else
216 {
217 hh->hh_systyp = hp->hp_rsystyp;
218 hh->hh_port = (u_char) inp->inp_lport;
219 }
220
221 /* give it the present sequence number */
222 if (hp->hp_flags & HM_NUMOPT)
223 hh->hh_seq = hp->hp_rseq;
224 else
225 hh->hh_seq = hp->hp_lseq;
226
227 len += sizeof(struct hmp_hdr);
228 /* fill in the rest */
229 hh->hh_passwd = hp->hp_rpasswd;
230 hh->hh_msgtyp = hp->hp_rmsgtyp;
231 hh->hh_ctlflg = hp->hp_ctlflg;
232 hh->hh_cksum = 0;
233 hh->hh_cksum = in_cksum(m,len);
234
235 /* IP header */
236 m->m_off -= sizeof(struct ip);
237 m->m_len += sizeof(struct ip);
238
239 ip = mtod(m,struct ip *);
240
241 ip->ip_hl = ip->ip_v = 0;
242 ip->ip_tos = 0;
243 ip->ip_id = ip->ip_off = 0;
244 ip->ip_p = IPPROTO_HMP;
245 ip->ip_len = htons(len);
246 ip->ip_src = inp->inp_laddr;
247 ip->ip_dst = inp->inp_faddr;
248 ip->ip_ttl = MAXTTL;
249
250 return(ip_send(inp,m,(int)len,0));
251
252 dropit :
253 m_freem(m);
254 return(error);
255 }
256
257 /**************************************************************************/
258 /* */
259 /* basically one large dispatch table. */
260 /* */
261 /**************************************************************************/
262
263 /* ARGSUSED */
264 hmp_usrreq(so,req,m,nam,rights)
265 struct socket *so;
266 int req;
267 struct mbuf *m, *nam, *rights;
268 {
269 register struct inpcb *inp = sotoinpcb(so);
270 register int error = 0;
271
272 if ((rights != (struct mbuf *)0) && (rights->m_len))
273 {
274 error = EINVAL;
275 goto release;
276 }
277
278 switch(req)
279 {
280 case PRU_ATTACH:
281 error = hmp_attach(so,&hmp);
282 break;
283
284 case PRU_DETACH:
285 error = hmp_detach(inp);
286 break;
287
288 case PRU_BIND:
289 error = hmp_bind(inp,nam);
290 break;
291
292 case PRU_CONNECT:
293 error = hmp_connect(inp,nam);
294 if (error == 0)
295 soisconnected(so);
296 break;
297
298 case PRU_DISCONNECT:
299 error = hmp_disconnect(inp);
300 if (error == 0)
301 soisdisconnected(so);
302 break;
303
304 case PRU_SHUTDOWN:
305 socantsendmore(so);
306 break;
307
308 case PRU_SEND:
309 {
310 struct in_addr sav_addr;
311
312 /* if nam not 0 then doing sendto(), else send() */
313 if (nam != (struct mbuf *)0)
314 {
315 sav_addr = inp->inp_laddr;
316 if (inp->inp_faddr.s_addr != INADDR_ANY)
317 {
318 error = EISCONN;
319 break;
320 }
321 if (error = hmp_connect(inp,nam))
322 break;
323 }
324 else if (inp->inp_faddr.s_addr == INADDR_ANY)
325 {
326 error = ENOTCONN;
327 break;
328 }
329
330 error = hmp_output(inp,m);
331 m = (struct mbuf *)0;
332
333 if (nam != (struct mbuf *)0)
334 {
335 hmp_disconnect(inp);
336 inp->inp_laddr = sav_addr;
337 }
338 }
339 break;
340
341 case PRU_ABORT:
342 hmp_detach(inp);
343 hmp_disconnect(inp);
344 sofree(so);
345 break;
346
347 case PRU_SOCKADDR:
348 in_setsockaddr(inp,nam);
349 break;
350
351 case PRU_PEERADDR:
352 in_setpeeraddr(inp,nam);
353 break;
354
355 case PRU_CONTROL:
356 /* not our ioctl, let lower level try ioctl */
357 error = ip_ioctl (inp, (int) m, (caddr_t) nam);
358 m = (struct mbuf *) NULL; /* don't want it freed */
359 break;
360
361 case PRU_SENSE:
362 m = (struct mbuf *)0;
363 /* fall thru.... */
364
365 case PRU_LISTEN:
366 case PRU_RCVD:
367 case PRU_RCVOOB:
368 case PRU_FASTTIMO:
369 case PRU_SLOWTIMO:
370 case PRU_PROTORCV:
371 case PRU_PROTOSEND:
372 case PRU_SENDOOB:
373 case PRU_CONNECT2:
374 case PRU_ACCEPT:
375 error = EOPNOTSUPP;
376 break;
377
378 default:
379 panic("hmp_usrreq");
380 }
381
382 release :
383 if (m != (struct mbuf *)0)
384 m_freem(m);
385
386 return(error);
387 }
388
389 /**************************************************************************/
390 /* */
391 /* */
392 /**************************************************************************/
393
hmp_abort(inp)394 hmp_abort(inp)
395 register struct inpcb *inp;
396 {
397 register struct socket *so = inp->inp_socket;
398
399 hmp_disconnect(inp);
400 in_pcbdisconnect(inp);
401 soisdisconnected(so);
402 }
403
404 /**************************************************************************/
405 /* */
406 /**************************************************************************/
407
hmp_ctloutput(req,so,level,optname,optval)408 hmp_ctloutput(req, so, level, optname, optval)
409 int req;
410 struct socket *so;
411 int level, optname;
412 struct mbuf **optval;
413 {
414 int s = splnet(); /* like PRU/packet/timer entry into net code */
415 int error;
416
417 /*
418 * see comments by tcp_ctloutput()
419 */
420 if (level == HMPROTO)
421 {
422 struct inpcb *inp;
423
424 inp = sotoinpcb(so);
425
426 switch(req)
427 {
428 case PRCO_GETOPT:
429 error = hmp_getopt(inp,optname,optval);
430 break;
431
432 case PRCO_SETOPT:
433 error = hmp_setopt(inp,optname,optval);
434 break;
435
436 default:
437 panic("hmp_ctloutput");
438 }
439 } else
440 error = ip_ctloutput(req,so,level,optname,optval);
441
442 splx(s);
443 return (error);
444 }
445
446 /**************************************************************************/
447 /* */
448 /**************************************************************************/
449
450 hmp_getopt(inp,optname,optval)
451 struct inpcb *inp;
452 int optname;
453 struct mbuf **optval;
454 {
455 int error = 0;
456
457 switch (optname)
458 {
459 #ifdef HMPTRAPS
460 case SOI_MONHOST:
461 error = getmonhosts(optval);
462 break;
463 #endif
464
465 default:
466 error = EOPNOTSUPP;
467 break;
468 }
469
470 return(error);
471 }
472
473 /**************************************************************************/
474 /* */
475 /**************************************************************************/
476
477 hmp_setopt(inp, optname, optval)
478 struct inpcb *inp;
479 int optname;
480 struct mbuf **optval;
481 {
482 register error = 0;
483
484 switch(optname)
485 {
486 #ifdef HMPTRAP
487 case SOI_MONHOST:
488 error = setmonhosts(*optval);
489 break;
490 #endif
491
492
493 default:
494 error = EOPNOTSUPP;
495 }
496
497 /* clean up for setsockopt */
498 if (*optval != 0)
499 m_freem(*optval);
500
501 return(error);
502 }
503
hmp_ctlinput(prc_code,arg)504 hmp_ctlinput (prc_code, arg)
505 caddr_t arg;
506 {
507 }
508 #endif HMP
509