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