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