xref: /original-bsd/sys/deprecated/bbnnet/hmp.c (revision e59fb703)
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 
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 
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 
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 
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 
504 hmp_ctlinput (prc_code, arg)
505 caddr_t arg;
506 {
507 }
508 #endif HMP
509