35 */ 36 37#include "opt_ipsec.h" 38#include "opt_mac.h" 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/mac.h> 43#include <sys/mbuf.h> 44#include <sys/protosw.h> 45#include <sys/socket.h> 46#include <sys/time.h> 47#include <sys/kernel.h> 48#include <sys/sysctl.h> 49 50#include <net/if.h> 51#include <net/if_types.h> 52#include <net/route.h> 53 54#define _IP_VHL 55#include <netinet/in.h> 56#include <netinet/in_systm.h> 57#include <netinet/in_var.h> 58#include <netinet/ip.h> 59#include <netinet/ip_icmp.h> 60#include <netinet/ip_var.h> 61#include <netinet/icmp_var.h> 62 63#ifdef IPSEC 64#include <netinet6/ipsec.h> 65#include <netkey/key.h> 66#endif 67 68#include <machine/in_cksum.h> 69 70/* 71 * ICMP routines: error generation, receive packet processing, and 72 * routines to turnaround packets back to the originator, and 73 * host table maintenance routines. 74 */ 75 76static struct icmpstat icmpstat; 77SYSCTL_STRUCT(_net_inet_icmp, ICMPCTL_STATS, stats, CTLFLAG_RW, 78 &icmpstat, icmpstat, ""); 79 80static int icmpmaskrepl = 0; 81SYSCTL_INT(_net_inet_icmp, ICMPCTL_MASKREPL, maskrepl, CTLFLAG_RW, 82 &icmpmaskrepl, 0, ""); 83 84static int drop_redirect = 0; 85SYSCTL_INT(_net_inet_icmp, OID_AUTO, drop_redirect, CTLFLAG_RW, 86 &drop_redirect, 0, ""); 87 88static int log_redirect = 0; 89SYSCTL_INT(_net_inet_icmp, OID_AUTO, log_redirect, CTLFLAG_RW, 90 &log_redirect, 0, ""); 91 92static int icmplim = 200; 93SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RW, 94 &icmplim, 0, ""); 95 96static int icmplim_output = 1; 97SYSCTL_INT(_net_inet_icmp, OID_AUTO, icmplim_output, CTLFLAG_RW, 98 &icmplim_output, 0, ""); 99 100/* 101 * ICMP broadcast echo sysctl 102 */ 103 104static int icmpbmcastecho = 0; 105SYSCTL_INT(_net_inet_icmp, OID_AUTO, bmcastecho, CTLFLAG_RW, 106 &icmpbmcastecho, 0, ""); 107 108 109#ifdef ICMPPRINTFS 110int icmpprintfs = 0; 111#endif 112 113static void icmp_reflect(struct mbuf *); 114static void icmp_send(struct mbuf *, struct mbuf *, struct route *); 115static int ip_next_mtu(int, int); 116 117extern struct protosw inetsw[]; 118 119/* 120 * Generate an error packet of type error 121 * in response to bad packet ip. 122 */ 123void 124icmp_error(n, type, code, dest, destifp) 125 struct mbuf *n; 126 int type, code; 127 n_long dest; 128 struct ifnet *destifp; 129{ 130 register struct ip *oip = mtod(n, struct ip *), *nip; 131 register unsigned oiplen = IP_VHL_HL(oip->ip_vhl) << 2; 132 register struct icmp *icp; 133 register struct mbuf *m; 134 unsigned icmplen; 135 136#ifdef ICMPPRINTFS 137 if (icmpprintfs) 138 printf("icmp_error(%p, %x, %d)\n", oip, type, code); 139#endif 140 if (type != ICMP_REDIRECT) 141 icmpstat.icps_error++; 142 /* 143 * Don't send error if not the first fragment of message. 144 * Don't error if the old packet protocol was ICMP 145 * error message, only known informational types. 146 */ 147 if (oip->ip_off &~ (IP_MF|IP_DF)) 148 goto freeit; 149 if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT && 150 n->m_len >= oiplen + ICMP_MINLEN && 151 !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiplen))->icmp_type)) { 152 icmpstat.icps_oldicmp++; 153 goto freeit; 154 } 155 /* Don't send error in response to a multicast or broadcast packet */ 156 if (n->m_flags & (M_BCAST|M_MCAST)) 157 goto freeit; 158 /* 159 * First, formulate icmp message 160 */ 161 m = m_gethdr(M_DONTWAIT, MT_HEADER); 162 if (m == NULL) 163 goto freeit; 164#ifdef MAC 165 mac_create_mbuf_netlayer(n, m); 166#endif 167 icmplen = min(oiplen + 8, oip->ip_len); 168 if (icmplen < sizeof(struct ip)) 169 panic("icmp_error: bad length"); 170 m->m_len = icmplen + ICMP_MINLEN; 171 MH_ALIGN(m, m->m_len); 172 icp = mtod(m, struct icmp *); 173 if ((u_int)type > ICMP_MAXTYPE) 174 panic("icmp_error"); 175 icmpstat.icps_outhist[type]++; 176 icp->icmp_type = type; 177 if (type == ICMP_REDIRECT) 178 icp->icmp_gwaddr.s_addr = dest; 179 else { 180 icp->icmp_void = 0; 181 /* 182 * The following assignments assume an overlay with the 183 * zeroed icmp_void field. 184 */ 185 if (type == ICMP_PARAMPROB) { 186 icp->icmp_pptr = code; 187 code = 0; 188 } else if (type == ICMP_UNREACH && 189 code == ICMP_UNREACH_NEEDFRAG && destifp) { 190 icp->icmp_nextmtu = htons(destifp->if_mtu); 191 } 192 } 193 194 icp->icmp_code = code; 195 m_copydata(n, 0, icmplen, (caddr_t)&icp->icmp_ip); 196 nip = &icp->icmp_ip; 197 198 /* 199 * Convert fields to network representation. 200 */ 201 nip->ip_len = htons(nip->ip_len); 202 nip->ip_off = htons(nip->ip_off); 203 204 /* 205 * Now, copy old ip header (without options) 206 * in front of icmp message. 207 */ 208 if (m->m_data - sizeof(struct ip) < m->m_pktdat) 209 panic("icmp len"); 210 m->m_data -= sizeof(struct ip); 211 m->m_len += sizeof(struct ip); 212 m->m_pkthdr.len = m->m_len; 213 m->m_pkthdr.rcvif = n->m_pkthdr.rcvif; 214 nip = mtod(m, struct ip *); 215 bcopy((caddr_t)oip, (caddr_t)nip, sizeof(struct ip)); 216 nip->ip_len = m->m_len; 217 nip->ip_vhl = IP_VHL_BORING; 218 nip->ip_p = IPPROTO_ICMP; 219 nip->ip_tos = 0; 220 icmp_reflect(m); 221 222freeit: 223 m_freem(n); 224} 225 226static struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET }; 227static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET }; 228static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET }; 229 230/* 231 * Process a received ICMP message. 232 */ 233void 234icmp_input(m, off) 235 register struct mbuf *m; 236 int off; 237{ 238 int hlen = off; 239 register struct icmp *icp; 240 register struct ip *ip = mtod(m, struct ip *); 241 int icmplen = ip->ip_len; 242 register int i; 243 struct in_ifaddr *ia; 244 void (*ctlfunc)(int, struct sockaddr *, void *); 245 int code; 246 247 /* 248 * Locate icmp structure in mbuf, and check 249 * that not corrupted and of at least minimum length. 250 */ 251#ifdef ICMPPRINTFS 252 if (icmpprintfs) { 253 char buf[4 * sizeof "123"]; 254 strcpy(buf, inet_ntoa(ip->ip_src)); 255 printf("icmp_input from %s to %s, len %d\n", 256 buf, inet_ntoa(ip->ip_dst), icmplen); 257 } 258#endif 259 if (icmplen < ICMP_MINLEN) { 260 icmpstat.icps_tooshort++; 261 goto freeit; 262 } 263 i = hlen + min(icmplen, ICMP_ADVLENMIN); 264 if (m->m_len < i && (m = m_pullup(m, i)) == 0) { 265 icmpstat.icps_tooshort++; 266 return; 267 } 268 ip = mtod(m, struct ip *); 269 m->m_len -= hlen; 270 m->m_data += hlen; 271 icp = mtod(m, struct icmp *); 272 if (in_cksum(m, icmplen)) { 273 icmpstat.icps_checksum++; 274 goto freeit; 275 } 276 m->m_len += hlen; 277 m->m_data -= hlen; 278 279 if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_type == IFT_FAITH) { 280 /* 281 * Deliver very specific ICMP type only. 282 */ 283 switch (icp->icmp_type) { 284 case ICMP_UNREACH: 285 case ICMP_TIMXCEED: 286 break; 287 default: 288 goto freeit; 289 } 290 } 291 292#ifdef ICMPPRINTFS 293 if (icmpprintfs) 294 printf("icmp_input, type %d code %d\n", icp->icmp_type, 295 icp->icmp_code); 296#endif 297 298 /* 299 * Message type specific processing. 300 */ 301 if (icp->icmp_type > ICMP_MAXTYPE) 302 goto raw; 303 icmpstat.icps_inhist[icp->icmp_type]++; 304 code = icp->icmp_code; 305 switch (icp->icmp_type) { 306 307 case ICMP_UNREACH: 308 switch (code) { 309 case ICMP_UNREACH_NET: 310 case ICMP_UNREACH_HOST: 311 case ICMP_UNREACH_SRCFAIL: 312 case ICMP_UNREACH_NET_UNKNOWN: 313 case ICMP_UNREACH_HOST_UNKNOWN: 314 case ICMP_UNREACH_ISOLATED: 315 case ICMP_UNREACH_TOSNET: 316 case ICMP_UNREACH_TOSHOST: 317 case ICMP_UNREACH_HOST_PRECEDENCE: 318 case ICMP_UNREACH_PRECEDENCE_CUTOFF: 319 code = PRC_UNREACH_NET; 320 break; 321 322 case ICMP_UNREACH_NEEDFRAG: 323 code = PRC_MSGSIZE; 324 break; 325 326 /* 327 * RFC 1122, Sections 3.2.2.1 and 4.2.3.9. 328 * Treat subcodes 2,3 as immediate RST 329 */ 330 case ICMP_UNREACH_PROTOCOL: 331 case ICMP_UNREACH_PORT: 332 code = PRC_UNREACH_PORT; 333 break; 334 335 case ICMP_UNREACH_NET_PROHIB: 336 case ICMP_UNREACH_HOST_PROHIB: 337 case ICMP_UNREACH_FILTER_PROHIB: 338 code = PRC_UNREACH_ADMIN_PROHIB; 339 break; 340 341 default: 342 goto badcode; 343 } 344 goto deliver; 345 346 case ICMP_TIMXCEED: 347 if (code > 1) 348 goto badcode; 349 code += PRC_TIMXCEED_INTRANS; 350 goto deliver; 351 352 case ICMP_PARAMPROB: 353 if (code > 1) 354 goto badcode; 355 code = PRC_PARAMPROB; 356 goto deliver; 357 358 case ICMP_SOURCEQUENCH: 359 if (code) 360 goto badcode; 361 code = PRC_QUENCH; 362 deliver: 363 /* 364 * Problem with datagram; advise higher level routines. 365 */ 366 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || 367 IP_VHL_HL(icp->icmp_ip.ip_vhl) < (sizeof(struct ip) >> 2)) { 368 icmpstat.icps_badlen++; 369 goto freeit; 370 } 371 icp->icmp_ip.ip_len = ntohs(icp->icmp_ip.ip_len); 372 /* Discard ICMP's in response to multicast packets */ 373 if (IN_MULTICAST(ntohl(icp->icmp_ip.ip_dst.s_addr))) 374 goto badcode; 375#ifdef ICMPPRINTFS 376 if (icmpprintfs) 377 printf("deliver to protocol %d\n", icp->icmp_ip.ip_p); 378#endif 379 icmpsrc.sin_addr = icp->icmp_ip.ip_dst; 380#if 1 381 /* 382 * MTU discovery: 383 * If we got a needfrag and there is a host route to the 384 * original destination, and the MTU is not locked, then 385 * set the MTU in the route to the suggested new value 386 * (if given) and then notify as usual. The ULPs will 387 * notice that the MTU has changed and adapt accordingly. 388 * If no new MTU was suggested, then we guess a new one 389 * less than the current value. If the new MTU is 390 * unreasonably small (arbitrarily set at 296), then 391 * we reset the MTU to the interface value and enable the 392 * lock bit, indicating that we are no longer doing MTU 393 * discovery. 394 */ 395 if (code == PRC_MSGSIZE) { 396 struct rtentry *rt; 397 int mtu; 398 399 rt = rtalloc1((struct sockaddr *)&icmpsrc, 0, 400 RTF_CLONING | RTF_PRCLONING); 401 if (rt && (rt->rt_flags & RTF_HOST) 402 && !(rt->rt_rmx.rmx_locks & RTV_MTU)) { 403 mtu = ntohs(icp->icmp_nextmtu); 404 if (!mtu) 405 mtu = ip_next_mtu(rt->rt_rmx.rmx_mtu, 406 1); 407#ifdef DEBUG_MTUDISC 408 printf("MTU for %s reduced to %d\n", 409 inet_ntoa(icmpsrc.sin_addr), mtu); 410#endif 411 if (mtu < 296) { 412 /* rt->rt_rmx.rmx_mtu = 413 rt->rt_ifp->if_mtu; */ 414 rt->rt_rmx.rmx_locks |= RTV_MTU; 415 } else if (rt->rt_rmx.rmx_mtu > mtu) { 416 rt->rt_rmx.rmx_mtu = mtu; 417 } 418 } 419 if (rt) 420 RTFREE(rt); 421 } 422 423#endif 424 /* 425 * XXX if the packet contains [IPv4 AH TCP], we can't make a 426 * notification to TCP layer. 427 */ 428 ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput; 429 if (ctlfunc) 430 (*ctlfunc)(code, (struct sockaddr *)&icmpsrc, 431 (void *)&icp->icmp_ip); 432 break; 433 434 badcode: 435 icmpstat.icps_badcode++; 436 break; 437 438 case ICMP_ECHO: 439 if (!icmpbmcastecho 440 && (m->m_flags & (M_MCAST | M_BCAST)) != 0) { 441 icmpstat.icps_bmcastecho++; 442 break; 443 } 444 icp->icmp_type = ICMP_ECHOREPLY; 445 if (badport_bandlim(BANDLIM_ICMP_ECHO) < 0) 446 goto freeit; 447 else 448 goto reflect; 449 450 case ICMP_TSTAMP: 451 if (!icmpbmcastecho 452 && (m->m_flags & (M_MCAST | M_BCAST)) != 0) { 453 icmpstat.icps_bmcasttstamp++; 454 break; 455 } 456 if (icmplen < ICMP_TSLEN) { 457 icmpstat.icps_badlen++; 458 break; 459 } 460 icp->icmp_type = ICMP_TSTAMPREPLY; 461 icp->icmp_rtime = iptime(); 462 icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */ 463 if (badport_bandlim(BANDLIM_ICMP_TSTAMP) < 0) 464 goto freeit; 465 else 466 goto reflect; 467 468 case ICMP_MASKREQ: 469 if (icmpmaskrepl == 0) 470 break; 471 /* 472 * We are not able to respond with all ones broadcast 473 * unless we receive it over a point-to-point interface. 474 */ 475 if (icmplen < ICMP_MASKLEN) 476 break; 477 switch (ip->ip_dst.s_addr) { 478 479 case INADDR_BROADCAST: 480 case INADDR_ANY: 481 icmpdst.sin_addr = ip->ip_src; 482 break; 483 484 default: 485 icmpdst.sin_addr = ip->ip_dst; 486 } 487 ia = (struct in_ifaddr *)ifaof_ifpforaddr( 488 (struct sockaddr *)&icmpdst, m->m_pkthdr.rcvif); 489 if (ia == 0) 490 break; 491 if (ia->ia_ifp == 0) 492 break; 493 icp->icmp_type = ICMP_MASKREPLY; 494 icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr; 495 if (ip->ip_src.s_addr == 0) { 496 if (ia->ia_ifp->if_flags & IFF_BROADCAST) 497 ip->ip_src = satosin(&ia->ia_broadaddr)->sin_addr; 498 else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT) 499 ip->ip_src = satosin(&ia->ia_dstaddr)->sin_addr; 500 } 501reflect: 502 ip->ip_len += hlen; /* since ip_input deducts this */ 503 icmpstat.icps_reflect++; 504 icmpstat.icps_outhist[icp->icmp_type]++; 505 icmp_reflect(m); 506 return; 507 508 case ICMP_REDIRECT: 509 if (log_redirect) { 510 u_long src, dst, gw; 511 512 src = ntohl(ip->ip_src.s_addr); 513 dst = ntohl(icp->icmp_ip.ip_dst.s_addr); 514 gw = ntohl(icp->icmp_gwaddr.s_addr); 515 printf("icmp redirect from %d.%d.%d.%d: " 516 "%d.%d.%d.%d => %d.%d.%d.%d\n", 517 (int)(src >> 24), (int)((src >> 16) & 0xff), 518 (int)((src >> 8) & 0xff), (int)(src & 0xff), 519 (int)(dst >> 24), (int)((dst >> 16) & 0xff), 520 (int)((dst >> 8) & 0xff), (int)(dst & 0xff), 521 (int)(gw >> 24), (int)((gw >> 16) & 0xff), 522 (int)((gw >> 8) & 0xff), (int)(gw & 0xff)); 523 } 524 if (drop_redirect) 525 break; 526 if (code > 3) 527 goto badcode; 528 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || 529 IP_VHL_HL(icp->icmp_ip.ip_vhl) < (sizeof(struct ip) >> 2)) { 530 icmpstat.icps_badlen++; 531 break; 532 } 533 /* 534 * Short circuit routing redirects to force 535 * immediate change in the kernel's routing 536 * tables. The message is also handed to anyone 537 * listening on a raw socket (e.g. the routing 538 * daemon for use in updating its tables). 539 */ 540 icmpgw.sin_addr = ip->ip_src; 541 icmpdst.sin_addr = icp->icmp_gwaddr; 542#ifdef ICMPPRINTFS 543 if (icmpprintfs) { 544 char buf[4 * sizeof "123"]; 545 strcpy(buf, inet_ntoa(icp->icmp_ip.ip_dst)); 546 547 printf("redirect dst %s to %s\n", 548 buf, inet_ntoa(icp->icmp_gwaddr)); 549 } 550#endif 551 icmpsrc.sin_addr = icp->icmp_ip.ip_dst; 552 rtredirect((struct sockaddr *)&icmpsrc, 553 (struct sockaddr *)&icmpdst, 554 (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST, 555 (struct sockaddr *)&icmpgw, (struct rtentry **)0); 556 pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&icmpsrc); 557#ifdef IPSEC 558 key_sa_routechange((struct sockaddr *)&icmpsrc); 559#endif 560 break; 561 562 /* 563 * No kernel processing for the following; 564 * just fall through to send to raw listener. 565 */ 566 case ICMP_ECHOREPLY: 567 case ICMP_ROUTERADVERT: 568 case ICMP_ROUTERSOLICIT: 569 case ICMP_TSTAMPREPLY: 570 case ICMP_IREQREPLY: 571 case ICMP_MASKREPLY: 572 default: 573 break; 574 } 575 576raw: 577 rip_input(m, off); 578 return; 579 580freeit: 581 m_freem(m); 582} 583 584/* 585 * Reflect the ip packet back to the source 586 */ 587static void 588icmp_reflect(m) 589 struct mbuf *m; 590{ 591 struct ip *ip = mtod(m, struct ip *); 592 struct ifaddr *ifa; 593 struct in_ifaddr *ia; 594 struct in_addr t; 595 struct mbuf *opts = 0; 596 int optlen = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof(struct ip); 597 struct route *ro = NULL, rt; 598 599 if (!in_canforward(ip->ip_src) && 600 ((ntohl(ip->ip_src.s_addr) & IN_CLASSA_NET) != 601 (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))) { 602 m_freem(m); /* Bad return address */ 603 icmpstat.icps_badaddr++; 604 goto done; /* Ip_output() will check for broadcast */ 605 } 606 t = ip->ip_dst; 607 ip->ip_dst = ip->ip_src; 608 ro = &rt; 609 bzero(ro, sizeof(*ro)); 610 /* 611 * If the incoming packet was addressed directly to us, 612 * use dst as the src for the reply. Otherwise (broadcast 613 * or anonymous), use the address which corresponds 614 * to the incoming interface. 615 */ 616 LIST_FOREACH(ia, INADDR_HASH(t.s_addr), ia_hash) 617 if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr) 618 goto match; 619 if (m->m_pkthdr.rcvif != NULL && 620 m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) { 621 TAILQ_FOREACH(ifa, &m->m_pkthdr.rcvif->if_addrhead, ifa_link) { 622 if (ifa->ifa_addr->sa_family != AF_INET) 623 continue; 624 ia = ifatoia(ifa); 625 if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr == 626 t.s_addr) 627 goto match; 628 } 629 } 630 ia = ip_rtaddr(ip->ip_dst, ro); 631 /* We need a route to do anything useful. */ 632 if (ia == NULL) { 633 m_freem(m); 634 icmpstat.icps_noroute++; 635 goto done; 636 } 637match: 638 t = IA_SIN(ia)->sin_addr; 639 ip->ip_src = t; 640 ip->ip_ttl = ip_defttl; 641 642 if (optlen > 0) { 643 register u_char *cp; 644 int opt, cnt; 645 u_int len; 646 647 /* 648 * Retrieve any source routing from the incoming packet; 649 * add on any record-route or timestamp options. 650 */ 651 cp = (u_char *) (ip + 1); 652 if ((opts = ip_srcroute()) == 0 && 653 (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) { 654 opts->m_len = sizeof(struct in_addr); 655 mtod(opts, struct in_addr *)->s_addr = 0; 656 } 657 if (opts) { 658#ifdef ICMPPRINTFS 659 if (icmpprintfs) 660 printf("icmp_reflect optlen %d rt %d => ", 661 optlen, opts->m_len); 662#endif 663 for (cnt = optlen; cnt > 0; cnt -= len, cp += len) { 664 opt = cp[IPOPT_OPTVAL]; 665 if (opt == IPOPT_EOL) 666 break; 667 if (opt == IPOPT_NOP) 668 len = 1; 669 else { 670 if (cnt < IPOPT_OLEN + sizeof(*cp)) 671 break; 672 len = cp[IPOPT_OLEN]; 673 if (len < IPOPT_OLEN + sizeof(*cp) || 674 len > cnt) 675 break; 676 } 677 /* 678 * Should check for overflow, but it "can't happen" 679 */ 680 if (opt == IPOPT_RR || opt == IPOPT_TS || 681 opt == IPOPT_SECURITY) { 682 bcopy((caddr_t)cp, 683 mtod(opts, caddr_t) + opts->m_len, len); 684 opts->m_len += len; 685 } 686 } 687 /* Terminate & pad, if necessary */ 688 cnt = opts->m_len % 4; 689 if (cnt) { 690 for (; cnt < 4; cnt++) { 691 *(mtod(opts, caddr_t) + opts->m_len) = 692 IPOPT_EOL; 693 opts->m_len++; 694 } 695 } 696#ifdef ICMPPRINTFS 697 if (icmpprintfs) 698 printf("%d\n", opts->m_len); 699#endif 700 } 701 /* 702 * Now strip out original options by copying rest of first 703 * mbuf's data back, and adjust the IP length. 704 */ 705 ip->ip_len -= optlen; 706 ip->ip_vhl = IP_VHL_BORING; 707 m->m_len -= optlen; 708 if (m->m_flags & M_PKTHDR) 709 m->m_pkthdr.len -= optlen; 710 optlen += sizeof(struct ip); 711 bcopy((caddr_t)ip + optlen, (caddr_t)(ip + 1), 712 (unsigned)(m->m_len - sizeof(struct ip))); 713 } 714 m->m_flags &= ~(M_BCAST|M_MCAST); 715 icmp_send(m, opts, ro); 716done: 717 if (opts) 718 (void)m_free(opts); 719 if (ro && ro->ro_rt) 720 RTFREE(ro->ro_rt); 721} 722 723/* 724 * Send an icmp packet back to the ip level, 725 * after supplying a checksum. 726 */ 727static void 728icmp_send(m, opts, rt) 729 register struct mbuf *m; 730 struct mbuf *opts; 731 struct route *rt; 732{ 733 register struct ip *ip = mtod(m, struct ip *); 734 register int hlen; 735 register struct icmp *icp; 736 737 hlen = IP_VHL_HL(ip->ip_vhl) << 2; 738 m->m_data += hlen; 739 m->m_len -= hlen; 740 icp = mtod(m, struct icmp *); 741 icp->icmp_cksum = 0; 742 icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen); 743 m->m_data -= hlen; 744 m->m_len += hlen; 745 m->m_pkthdr.rcvif = (struct ifnet *)0; 746#ifdef ICMPPRINTFS 747 if (icmpprintfs) { 748 char buf[4 * sizeof "123"]; 749 strcpy(buf, inet_ntoa(ip->ip_dst)); 750 printf("icmp_send dst %s src %s\n", 751 buf, inet_ntoa(ip->ip_src)); 752 } 753#endif
|