1 #ifdef RCSIDENT 2 static char rcsident[] = "$Header: raw_input.c,v 1.17 85/07/31 09:33:16 walsh Exp $"; 3 #endif 4 5 #include "../h/param.h" 6 #include "../h/dir.h" 7 #include "../h/user.h" 8 #include "../machine/mtpr.h" 9 #include "../h/mbuf.h" 10 #include "../h/socket.h" 11 #include "../h/socketvar.h" 12 13 #include "../net/if.h" 14 #include "../net/netisr.h" 15 #include "../net/route.h" 16 #include "../net/raw_cb.h" 17 18 #include "../bbnnet/in.h" 19 #include "../bbnnet/net.h" 20 #include "../bbnnet/in_pcb.h" 21 #include "../bbnnet/in_var.h" 22 #include "../bbnnet/ip.h" 23 #include "../bbnnet/fsm.h" 24 #include "../bbnnet/tcp.h" 25 #include "../bbnnet/icmp.h" 26 #include "../bbnnet/udp.h" 27 #ifdef HMP 28 #include "../bbnnet/hmp.h" 29 #endif HMP 30 #include "../bbnnet/nopcb.h" 31 32 /* 33 * Sort INET packets for user(s). To get a packet, socket must match: 34 * 35 * raw_ip_proto 36 * domain (INET) 37 * protocol (TCP/UDP/ICMP) 38 * raw_ip_dst 39 * domain (INET) 40 * address, but not port, if connected(2) 41 * raw_ip_src 42 * domain (INET) 43 * address, but not port, if bound(2) 44 * 45 * Called from ip_input() for packets that were well-formed enough to get 46 * passed up to TCP/UDP/ICMP. 47 */ 48 struct sockaddr_in raw_ip_dst = 49 { 50 AF_INET 51 } ; 52 struct sockaddr_in raw_ip_src = 53 { 54 AF_INET 55 } ; 56 struct sockproto raw_ip_proto = 57 { 58 PF_INET 59 } ; 60 61 raw_ip_input(m) 62 struct mbuf *m; 63 { 64 register struct ip *ip = mtod(m, struct ip *); 65 66 raw_ip_proto.sp_protocol = ip->ip_p; 67 raw_ip_dst.sin_addr.s_addr = ip->ip_dst.s_addr; 68 raw_ip_src.sin_addr.s_addr = ip->ip_src.s_addr; 69 70 raw_input (m, &raw_ip_proto, (struct sockaddr *)&raw_ip_src, 71 (struct sockaddr *)&raw_ip_dst); 72 } 73 74 /* 75 * Bad ip packets, which are taken care of via calls to ip_log() and netlog(). 76 */ 77 struct sockaddr_in netlog_dst = 78 { 79 AF_INET 80 } ; 81 struct sockaddr_in netlog_src = 82 { 83 AF_INET 84 } ; 85 struct sockproto netlog_proto = 86 { 87 PF_INET, NETLOG_PROTO 88 } ; 89 90 netlog(m) 91 struct mbuf *m; 92 { 93 raw_input (m, &netlog_proto, (struct sockaddr *)&netlog_src, 94 (struct sockaddr *)&netlog_dst); 95 } 96 97 #ifdef AF_TCPDEBUG 98 /* 99 * TCP debugging log 100 * 101 * Though the mbuf contains a copy of the tcpcb, and thus a pointer to the 102 * inpcb, kernel can't do address sorting since this may point within a freed 103 * (and perhaps now recycled) mbuf. Remember that this logging is done after 104 * state changes (closing). 105 */ 106 struct sockaddr_in tcpdebug_dst = 107 { 108 AF_TCPDEBUG 109 } ; 110 struct sockaddr_in tcpdebug_src = 111 { 112 AF_TCPDEBUG 113 } ; 114 struct sockproto tcpdebug_proto = 115 { 116 PF_TCPDEBUG, 0 117 } ; 118 119 tcpdebuglog(m) 120 struct mbuf *m; 121 { 122 raw_input (m, &tcpdebug_proto, (struct sockaddr *)&tcpdebug_src, 123 (struct sockaddr *)&tcpdebug_dst); 124 } 125 #else 126 tcpdebuglog(m) 127 struct mbuf *m; 128 { 129 m_freem(m); 130 } 131 #endif 132 133 #ifdef AF_RDPDEBUG 134 struct sockaddr_in rdpdebug_dst = 135 { 136 AF_RDPDEBUG 137 } ; 138 struct sockaddr_in rdpdebug_src = 139 { 140 AF_RDPDEBUG 141 } ; 142 struct sockproto rdpdebug_proto = 143 { 144 PF_RDPDEBUG, 0 145 } ; 146 147 rdpdebuglog(m) 148 struct mbuf *m; 149 { 150 raw_input (m, &rdpdebug_proto, (struct sockaddr *)&rdpdebug_src, 151 (struct sockaddr *)&rdpdebug_dst); 152 } 153 #else 154 rdpdebuglog(m) 155 struct mbuf *m; 156 { 157 m_freem(m); 158 } 159 #endif 160 161 162 struct mbuf *m_bpullup(m0, len) 163 struct mbuf *m0; 164 int len; 165 { 166 register struct mbuf *m, *n; 167 unsigned count; 168 169 n = m0; 170 if (len > MLEN) 171 { 172 m_freem(n); 173 return ((struct mbuf *) NULL); 174 } 175 #ifdef MBUF_DEBUG 176 m = m_get(M_DONTWAIT, n->m_type); 177 #else 178 MGET(m, M_DONTWAIT, n->m_type); 179 #endif 180 if (m == 0) 181 { 182 m_freem(n); 183 return ((struct mbuf *) NULL); 184 } 185 m->m_len = 0; 186 m->m_off = MMAXOFF - len; /* -- difference from m_pullup -- */ 187 do 188 { 189 count = MIN(len, n->m_len); 190 bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len, count); 191 len -= count; 192 m->m_len += count; 193 n->m_off += count; 194 n->m_len -= count; 195 if (n->m_len) 196 break; 197 n = m_free(n); 198 } 199 while (n); 200 201 if (len) 202 { 203 (void) m_free(m); 204 m_freem(n); 205 return ((struct mbuf *) NULL); 206 } 207 m->m_next = n; 208 return (m); 209 } 210 211 /* 212 * output function called from net/raw_usrreq 213 */ 214 215 /* ARGSUSED */ 216 raw_ip_output (m0, so) 217 struct mbuf *m0; 218 struct socket *so; 219 { 220 register struct mbuf *m; 221 register struct ip *ip; 222 register int len; 223 int retval; 224 225 /* 226 * verify length of datagram, get IP header at end of mbuf so can 227 * prepend local net header. 228 */ 229 len = 0; 230 for (m = m0 ; m ; m = m->m_next) 231 len += m->m_len; 232 if (len < sizeof(struct ip)) 233 { 234 m_freem(m0); 235 return(EMSGSIZE); /* ### */ 236 } 237 if ((m = m_bpullup(m0, sizeof(struct ip))) == NULL) 238 return (ENOBUFS); 239 ip = mtod(m, struct ip *); 240 if ((ntohs((u_short)ip->ip_len) != len) || 241 ((ip->ip_hl << IP_HLSHIFT) > len)) 242 { 243 m_freem(m); 244 return(EMSGSIZE); /* ### */ 245 } 246 247 #ifdef notdef 248 /* have to be super-user anyway to do this. 249 * Cronus wants to be able to forward broadcast UDP packets. 250 */ 251 252 /* 253 * verify that addresses are valid 254 */ 255 if (in_broadcast(ip->ip_src) || (in_iawithaddr(ip->ip_src, TRUE) == 0)) 256 #else 257 if (in_broadcast(ip->ip_src)) 258 #endif 259 { 260 m_freem(m); 261 return (EADDRNOTAVAIL); 262 } 263 264 NOPCB_IPSEND (m, len, TRUE, retval); 265 return (retval); 266 } 267 268 269 270 /* 271 * Send out an icmp packet. Use the user's ICMP header, and our own IP 272 * header. 273 */ 274 /* ARGSUSED */ 275 raw_icmp_output (m0, so) 276 struct mbuf *m0; 277 struct socket *so; 278 { 279 register struct mbuf *m; 280 register struct icmp *p; 281 register struct ip *ip; 282 register struct rawcb *rcb; 283 int len; 284 int retval; 285 286 rcb = sotorawcb(so); 287 if (!(rcb->rcb_flags & RAW_FADDR)) 288 { 289 m_freem(m0); 290 return(EDESTADDRREQ); 291 } 292 293 /* 294 * find length of datagram 295 */ 296 len = 0; 297 for (m = m0 ; m ; m = m->m_next) 298 len += m->m_len; 299 if (len < ICMPSIZE) 300 { 301 m_freem(m0); 302 return (EMSGSIZE); /* ### */ 303 } 304 305 /* 306 * Pull up user's ICMP header so we can prepend IP header later. 307 */ 308 if ((m = m_bpullup(m0, ICMPSIZE)) == NULL) 309 return (ENOBUFS); 310 311 /* 312 * "Verify" ICMP header. Accept user's type and code. 313 */ 314 p = mtod(m, struct icmp *); 315 316 /* 317 * Use our own checksum, though. It'll be at least as fast as the 318 * user's and we'll have to use those CPU cycles sometime. 319 */ 320 p->ic_sum = 0; 321 p->ic_sum = in_cksum(m, len); 322 323 /* 324 * Fill in IP header and send it 325 */ 326 m->m_off -= sizeof(struct ip); 327 m->m_len += sizeof(struct ip); 328 ip = mtod(m, struct ip *); 329 ip->ip_p = IPPROTO_ICMP; 330 ip->ip_tos = 0; 331 ip->ip_dst.s_addr = 332 ((struct sockaddr_in *) &rcb->rcb_faddr)->sin_addr.s_addr; 333 334 if (rcb->rcb_flags & RAW_LADDR) 335 { 336 ip->ip_src.s_addr = 337 ((struct sockaddr_in *) &rcb->rcb_laddr)->sin_addr.s_addr; 338 } 339 else 340 { 341 /* 342 * We may examine the routing tables twice. 343 * perhaps if this gets used a lot, it can be changed. 344 */ 345 struct route r; 346 struct rtentry *rt; 347 348 bzero ((caddr_t) &r, sizeof(r)); 349 ((struct sockaddr_in *) (&r.ro_dst)) ->sin_family = AF_INET; 350 ((struct sockaddr_in *) (&r.ro_dst)) ->sin_addr.s_addr = 351 ip->ip_dst.s_addr; 352 rtalloc(&r); 353 if (rt = r.ro_rt) 354 { 355 ip->ip_src = IA_INADDR(in_iafromif(rt->rt_ifp)); 356 rtfree (rt); 357 } 358 else 359 { 360 m_freem(m); 361 return (ENETUNREACH); 362 } 363 } 364 365 NOPCB_IPSEND (m, len, FALSE, retval); 366 return (retval); 367 } 368 369 #ifdef NSIP 370 /* 371 * Generate IP header and pass packet to ip_output. 372 * Tack on options user may have setup with control call. 373 */ 374 rip_output(m0, so) 375 struct mbuf *m0; 376 struct socket *so; 377 { 378 register struct mbuf *m; 379 380 /* 381 * get an mbuf for IP header. 382 */ 383 m = m_get(M_DONTWAIT, MT_HEADER); 384 if (m == NULL) 385 { 386 m_freem(m0); 387 return (ENOBUFS); 388 } 389 390 /* 391 * Fill in IP header as needed. 392 */ 393 m->m_off = MMAXOFF - sizeof(struct ip); 394 m->m_len = sizeof(struct ip); 395 m->m_next = m0; 396 { 397 register struct ip *ip; 398 register struct rawcb *rcb = sotorawcb(so); 399 400 ip = mtod(m, struct ip *); 401 ip->ip_p = rcb->rcb_proto.sp_protocol; 402 ip->ip_tos = 0; 403 ip->ip_dst.s_addr = 404 ((struct sockaddr_in *) &rcb->rcb_faddr)->sin_addr.s_addr; 405 if (rcb->rcb_flags & RAW_LADDR) 406 ip->ip_src.s_addr = 407 ((struct sockaddr_in *) &rcb->rcb_laddr)->sin_addr.s_addr; 408 else 409 ip->ip_src.s_addr = 0; 410 } 411 412 { 413 register int retval; 414 register int len; 415 416 /* 417 * Calculate data length 418 */ 419 len = 0; 420 while (m0) 421 { 422 len += m0->m_len; 423 m0 = m0->m_next; 424 } 425 426 427 NOPCB_IPSEND (m, len, FALSE, retval); 428 return (retval); 429 } 430 } 431 #endif 432 433 /* 434 * The UDP header is so small and simple, the user should either: 435 * 1. go all the way and use a raw IP socket 436 * or 2. use send(2) type system calls. 437 */ 438 /* ARGSUSED */ 439 raw_udp_output (m0, so) 440 struct mbuf *m0; 441 struct socket *so; 442 { 443 m_freem(m0); 444 return (EOPNOTSUPP); 445 } 446 447 /* 448 * TCP requires a lot of state information. Sure we could try to verify the 449 * user's header and pass it on to ip, but unless debugging a new version 450 * in user code with a different protocol number, probably shouldn't ship 451 * out tcp packets, since we'll get packets in reply that might screw us up. 452 * 453 * And how does the sending of a single tcp packet make sense? 454 */ 455 /* ARGSUSED */ 456 raw_tcp_output (m0, so) 457 struct mbuf *m0; 458 struct socket *so; 459 { 460 m_freem(m0); 461 return (EOPNOTSUPP); 462 } 463 464 #ifdef RDP 465 /* 466 * ditto TCP for RDP 467 */ 468 /* ARGSUSED */ 469 raw_rdp_output (m0, so) 470 struct mbuf *m0; 471 struct socket *so; 472 { 473 m_freem(m0); 474 return(EOPNOTSUPP); 475 } 476 #endif 477 478 /* 479 * use the user level stuff to send -- much simpler 480 */ 481 482 #ifdef HMP 483 /* ARGSUSED */ 484 raw_hmp_output (m0, so) 485 struct mbuf *m0; 486 struct socket *so; 487 { 488 m_freem(m0); 489 return(EOPNOTSUPP); 490 } 491 #endif 492