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