ip_icmp.c (1829d5da5355930d5cfa8ec8add8ff47dc0bebab) | ip_icmp.c (e27b0c87759d9d7a6eebca60bc82f171fbf36afc) |
---|---|
1/*- 2 * Copyright (c) 1982, 1986, 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 166 unchanged lines hidden (view full) --- 175 unsigned icmplen, icmpelen, nlen; 176 177 KASSERT((u_int)type <= ICMP_MAXTYPE, ("%s: illegal ICMP type", __func__)); 178#ifdef ICMPPRINTFS 179 if (icmpprintfs) 180 printf("icmp_error(%p, %x, %d)\n", oip, type, code); 181#endif 182 if (type != ICMP_REDIRECT) | 1/*- 2 * Copyright (c) 1982, 1986, 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 166 unchanged lines hidden (view full) --- 175 unsigned icmplen, icmpelen, nlen; 176 177 KASSERT((u_int)type <= ICMP_MAXTYPE, ("%s: illegal ICMP type", __func__)); 178#ifdef ICMPPRINTFS 179 if (icmpprintfs) 180 printf("icmp_error(%p, %x, %d)\n", oip, type, code); 181#endif 182 if (type != ICMP_REDIRECT) |
183 V_icmpstat.icps_error++; | 183 ICMPSTAT_INC(icps_error); |
184 /* 185 * Don't send error: 186 * if the original packet was encrypted. 187 * if not the first fragment of message. 188 * in response to a multicast or broadcast packet. 189 * if the old packet protocol was an ICMP error message. 190 */ 191 if (n->m_flags & M_DECRYPTED) 192 goto freeit; 193 if (oip->ip_off & ~(IP_MF|IP_DF)) 194 goto freeit; 195 if (n->m_flags & (M_BCAST|M_MCAST)) 196 goto freeit; 197 if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT && 198 n->m_len >= oiphlen + ICMP_MINLEN && 199 !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiphlen))->icmp_type)) { | 184 /* 185 * Don't send error: 186 * if the original packet was encrypted. 187 * if not the first fragment of message. 188 * in response to a multicast or broadcast packet. 189 * if the old packet protocol was an ICMP error message. 190 */ 191 if (n->m_flags & M_DECRYPTED) 192 goto freeit; 193 if (oip->ip_off & ~(IP_MF|IP_DF)) 194 goto freeit; 195 if (n->m_flags & (M_BCAST|M_MCAST)) 196 goto freeit; 197 if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT && 198 n->m_len >= oiphlen + ICMP_MINLEN && 199 !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiphlen))->icmp_type)) { |
200 V_icmpstat.icps_oldicmp++; | 200 ICMPSTAT_INC(icps_oldicmp); |
201 goto freeit; 202 } 203 /* Drop if IP header plus 8 bytes is not contignous in first mbuf. */ 204 if (oiphlen + 8 > n->m_len) 205 goto freeit; 206 /* 207 * Calculate length to quote from original packet and 208 * prevent the ICMP mbuf from overflowing. --- 43 unchanged lines hidden (view full) --- 252 m_align(m, ICMP_MINLEN + icmplen); 253 m->m_len = ICMP_MINLEN + icmplen; 254 255 /* XXX MRT make the outgoing packet use the same FIB 256 * that was associated with the incoming packet 257 */ 258 M_SETFIB(m, M_GETFIB(n)); 259 icp = mtod(m, struct icmp *); | 201 goto freeit; 202 } 203 /* Drop if IP header plus 8 bytes is not contignous in first mbuf. */ 204 if (oiphlen + 8 > n->m_len) 205 goto freeit; 206 /* 207 * Calculate length to quote from original packet and 208 * prevent the ICMP mbuf from overflowing. --- 43 unchanged lines hidden (view full) --- 252 m_align(m, ICMP_MINLEN + icmplen); 253 m->m_len = ICMP_MINLEN + icmplen; 254 255 /* XXX MRT make the outgoing packet use the same FIB 256 * that was associated with the incoming packet 257 */ 258 M_SETFIB(m, M_GETFIB(n)); 259 icp = mtod(m, struct icmp *); |
260 V_icmpstat.icps_outhist[type]++; | 260 ICMPSTAT_INC(icps_outhist[type]); |
261 icp->icmp_type = type; 262 if (type == ICMP_REDIRECT) 263 icp->icmp_gwaddr.s_addr = dest; 264 else { 265 icp->icmp_void = 0; 266 /* 267 * The following assignments assume an overlay with the 268 * just zeroed icmp_void field. --- 66 unchanged lines hidden (view full) --- 335 if (icmpprintfs) { 336 char buf[4 * sizeof "123"]; 337 strcpy(buf, inet_ntoa(ip->ip_src)); 338 printf("icmp_input from %s to %s, len %d\n", 339 buf, inet_ntoa(ip->ip_dst), icmplen); 340 } 341#endif 342 if (icmplen < ICMP_MINLEN) { | 261 icp->icmp_type = type; 262 if (type == ICMP_REDIRECT) 263 icp->icmp_gwaddr.s_addr = dest; 264 else { 265 icp->icmp_void = 0; 266 /* 267 * The following assignments assume an overlay with the 268 * just zeroed icmp_void field. --- 66 unchanged lines hidden (view full) --- 335 if (icmpprintfs) { 336 char buf[4 * sizeof "123"]; 337 strcpy(buf, inet_ntoa(ip->ip_src)); 338 printf("icmp_input from %s to %s, len %d\n", 339 buf, inet_ntoa(ip->ip_dst), icmplen); 340 } 341#endif 342 if (icmplen < ICMP_MINLEN) { |
343 V_icmpstat.icps_tooshort++; | 343 ICMPSTAT_INC(icps_tooshort); |
344 goto freeit; 345 } 346 i = hlen + min(icmplen, ICMP_ADVLENMIN); 347 if (m->m_len < i && (m = m_pullup(m, i)) == 0) { | 344 goto freeit; 345 } 346 i = hlen + min(icmplen, ICMP_ADVLENMIN); 347 if (m->m_len < i && (m = m_pullup(m, i)) == 0) { |
348 V_icmpstat.icps_tooshort++; | 348 ICMPSTAT_INC(icps_tooshort); |
349 return; 350 } 351 ip = mtod(m, struct ip *); 352 m->m_len -= hlen; 353 m->m_data += hlen; 354 icp = mtod(m, struct icmp *); 355 if (in_cksum(m, icmplen)) { | 349 return; 350 } 351 ip = mtod(m, struct ip *); 352 m->m_len -= hlen; 353 m->m_data += hlen; 354 icp = mtod(m, struct icmp *); 355 if (in_cksum(m, icmplen)) { |
356 V_icmpstat.icps_checksum++; | 356 ICMPSTAT_INC(icps_checksum); |
357 goto freeit; 358 } 359 m->m_len += hlen; 360 m->m_data -= hlen; 361 362 if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_type == IFT_FAITH) { 363 /* 364 * Deliver very specific ICMP type only. --- 25 unchanged lines hidden (view full) --- 390 icmpsrc.sin_family = AF_INET; 391 bzero(&icmpdst, sizeof(icmpdst)); 392 icmpdst.sin_len = sizeof(struct sockaddr_in); 393 icmpdst.sin_family = AF_INET; 394 bzero(&icmpgw, sizeof(icmpgw)); 395 icmpgw.sin_len = sizeof(struct sockaddr_in); 396 icmpgw.sin_family = AF_INET; 397 | 357 goto freeit; 358 } 359 m->m_len += hlen; 360 m->m_data -= hlen; 361 362 if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_type == IFT_FAITH) { 363 /* 364 * Deliver very specific ICMP type only. --- 25 unchanged lines hidden (view full) --- 390 icmpsrc.sin_family = AF_INET; 391 bzero(&icmpdst, sizeof(icmpdst)); 392 icmpdst.sin_len = sizeof(struct sockaddr_in); 393 icmpdst.sin_family = AF_INET; 394 bzero(&icmpgw, sizeof(icmpgw)); 395 icmpgw.sin_len = sizeof(struct sockaddr_in); 396 icmpgw.sin_family = AF_INET; 397 |
398 V_icmpstat.icps_inhist[icp->icmp_type]++; | 398 ICMPSTAT_INC(icps_inhist[icp->icmp_type]); |
399 code = icp->icmp_code; 400 switch (icp->icmp_type) { 401 402 case ICMP_UNREACH: 403 switch (code) { 404 case ICMP_UNREACH_NET: 405 case ICMP_UNREACH_HOST: 406 case ICMP_UNREACH_SRCFAIL: --- 48 unchanged lines hidden (view full) --- 455 goto badcode; 456 code = PRC_QUENCH; 457 deliver: 458 /* 459 * Problem with datagram; advise higher level routines. 460 */ 461 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || 462 icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) { | 399 code = icp->icmp_code; 400 switch (icp->icmp_type) { 401 402 case ICMP_UNREACH: 403 switch (code) { 404 case ICMP_UNREACH_NET: 405 case ICMP_UNREACH_HOST: 406 case ICMP_UNREACH_SRCFAIL: --- 48 unchanged lines hidden (view full) --- 455 goto badcode; 456 code = PRC_QUENCH; 457 deliver: 458 /* 459 * Problem with datagram; advise higher level routines. 460 */ 461 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || 462 icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) { |
463 V_icmpstat.icps_badlen++; | 463 ICMPSTAT_INC(icps_badlen); |
464 goto freeit; 465 } 466 icp->icmp_ip.ip_len = ntohs(icp->icmp_ip.ip_len); 467 /* Discard ICMP's in response to multicast packets */ 468 if (IN_MULTICAST(ntohl(icp->icmp_ip.ip_dst.s_addr))) 469 goto badcode; 470#ifdef ICMPPRINTFS 471 if (icmpprintfs) --- 6 unchanged lines hidden (view full) --- 478 */ 479 ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput; 480 if (ctlfunc) 481 (*ctlfunc)(code, (struct sockaddr *)&icmpsrc, 482 (void *)&icp->icmp_ip); 483 break; 484 485 badcode: | 464 goto freeit; 465 } 466 icp->icmp_ip.ip_len = ntohs(icp->icmp_ip.ip_len); 467 /* Discard ICMP's in response to multicast packets */ 468 if (IN_MULTICAST(ntohl(icp->icmp_ip.ip_dst.s_addr))) 469 goto badcode; 470#ifdef ICMPPRINTFS 471 if (icmpprintfs) --- 6 unchanged lines hidden (view full) --- 478 */ 479 ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput; 480 if (ctlfunc) 481 (*ctlfunc)(code, (struct sockaddr *)&icmpsrc, 482 (void *)&icp->icmp_ip); 483 break; 484 485 badcode: |
486 V_icmpstat.icps_badcode++; | 486 ICMPSTAT_INC(icps_badcode); |
487 break; 488 489 case ICMP_ECHO: 490 if (!V_icmpbmcastecho 491 && (m->m_flags & (M_MCAST | M_BCAST)) != 0) { | 487 break; 488 489 case ICMP_ECHO: 490 if (!V_icmpbmcastecho 491 && (m->m_flags & (M_MCAST | M_BCAST)) != 0) { |
492 V_icmpstat.icps_bmcastecho++; | 492 ICMPSTAT_INC(icps_bmcastecho); |
493 break; 494 } 495 icp->icmp_type = ICMP_ECHOREPLY; 496 if (badport_bandlim(BANDLIM_ICMP_ECHO) < 0) 497 goto freeit; 498 else 499 goto reflect; 500 501 case ICMP_TSTAMP: 502 if (!V_icmpbmcastecho 503 && (m->m_flags & (M_MCAST | M_BCAST)) != 0) { | 493 break; 494 } 495 icp->icmp_type = ICMP_ECHOREPLY; 496 if (badport_bandlim(BANDLIM_ICMP_ECHO) < 0) 497 goto freeit; 498 else 499 goto reflect; 500 501 case ICMP_TSTAMP: 502 if (!V_icmpbmcastecho 503 && (m->m_flags & (M_MCAST | M_BCAST)) != 0) { |
504 V_icmpstat.icps_bmcasttstamp++; | 504 ICMPSTAT_INC(icps_bmcasttstamp); |
505 break; 506 } 507 if (icmplen < ICMP_TSLEN) { | 505 break; 506 } 507 if (icmplen < ICMP_TSLEN) { |
508 V_icmpstat.icps_badlen++; | 508 ICMPSTAT_INC(icps_badlen); |
509 break; 510 } 511 icp->icmp_type = ICMP_TSTAMPREPLY; 512 icp->icmp_rtime = iptime(); 513 icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */ 514 if (badport_bandlim(BANDLIM_ICMP_TSTAMP) < 0) 515 goto freeit; 516 else --- 32 unchanged lines hidden (view full) --- 549 if (ip->ip_src.s_addr == 0) { 550 if (ia->ia_ifp->if_flags & IFF_BROADCAST) 551 ip->ip_src = satosin(&ia->ia_broadaddr)->sin_addr; 552 else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT) 553 ip->ip_src = satosin(&ia->ia_dstaddr)->sin_addr; 554 } 555reflect: 556 ip->ip_len += hlen; /* since ip_input deducts this */ | 509 break; 510 } 511 icp->icmp_type = ICMP_TSTAMPREPLY; 512 icp->icmp_rtime = iptime(); 513 icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */ 514 if (badport_bandlim(BANDLIM_ICMP_TSTAMP) < 0) 515 goto freeit; 516 else --- 32 unchanged lines hidden (view full) --- 549 if (ip->ip_src.s_addr == 0) { 550 if (ia->ia_ifp->if_flags & IFF_BROADCAST) 551 ip->ip_src = satosin(&ia->ia_broadaddr)->sin_addr; 552 else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT) 553 ip->ip_src = satosin(&ia->ia_dstaddr)->sin_addr; 554 } 555reflect: 556 ip->ip_len += hlen; /* since ip_input deducts this */ |
557 V_icmpstat.icps_reflect++; 558 V_icmpstat.icps_outhist[icp->icmp_type]++; | 557 ICMPSTAT_INC(icps_reflect); 558 ICMPSTAT_INC(icps_outhist[icp->icmp_type]); |
559 icmp_reflect(m); 560 return; 561 562 case ICMP_REDIRECT: 563 if (V_log_redirect) { 564 u_long src, dst, gw; 565 566 src = ntohl(ip->ip_src.s_addr); --- 13 unchanged lines hidden (view full) --- 580 * are acting as router. 581 */ 582 if (V_drop_redirect || V_ipforwarding) 583 break; 584 if (code > 3) 585 goto badcode; 586 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || 587 icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) { | 559 icmp_reflect(m); 560 return; 561 562 case ICMP_REDIRECT: 563 if (V_log_redirect) { 564 u_long src, dst, gw; 565 566 src = ntohl(ip->ip_src.s_addr); --- 13 unchanged lines hidden (view full) --- 580 * are acting as router. 581 */ 582 if (V_drop_redirect || V_ipforwarding) 583 break; 584 if (code > 3) 585 goto badcode; 586 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || 587 icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) { |
588 V_icmpstat.icps_badlen++; | 588 ICMPSTAT_INC(icps_badlen); |
589 break; 590 } 591 /* 592 * Short circuit routing redirects to force 593 * immediate change in the kernel's routing 594 * tables. The message is also handed to anyone 595 * listening on a raw socket (e.g. the routing 596 * daemon for use in updating its tables). --- 58 unchanged lines hidden (view full) --- 655 struct in_addr t; 656 struct mbuf *opts = 0; 657 int optlen = (ip->ip_hl << 2) - sizeof(struct ip); 658 659 if (IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || 660 IN_EXPERIMENTAL(ntohl(ip->ip_src.s_addr)) || 661 IN_ZERONET(ntohl(ip->ip_src.s_addr)) ) { 662 m_freem(m); /* Bad return address */ | 589 break; 590 } 591 /* 592 * Short circuit routing redirects to force 593 * immediate change in the kernel's routing 594 * tables. The message is also handed to anyone 595 * listening on a raw socket (e.g. the routing 596 * daemon for use in updating its tables). --- 58 unchanged lines hidden (view full) --- 655 struct in_addr t; 656 struct mbuf *opts = 0; 657 int optlen = (ip->ip_hl << 2) - sizeof(struct ip); 658 659 if (IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || 660 IN_EXPERIMENTAL(ntohl(ip->ip_src.s_addr)) || 661 IN_ZERONET(ntohl(ip->ip_src.s_addr)) ) { 662 m_freem(m); /* Bad return address */ |
663 V_icmpstat.icps_badaddr++; | 663 ICMPSTAT_INC(icps_badaddr); |
664 goto done; /* Ip_output() will check for broadcast */ 665 } 666 667 t = ip->ip_dst; 668 ip->ip_dst = ip->ip_src; 669 670 /* 671 * Source selection for ICMP replies: --- 52 unchanged lines hidden (view full) --- 724 * If the packet was transiting through us, use the address of 725 * the interface that is the closest to the packet source. 726 * When we don't have a route back to the packet source, stop here 727 * and drop the packet. 728 */ 729 ia = ip_rtaddr(ip->ip_dst, M_GETFIB(m)); 730 if (ia == NULL) { 731 m_freem(m); | 664 goto done; /* Ip_output() will check for broadcast */ 665 } 666 667 t = ip->ip_dst; 668 ip->ip_dst = ip->ip_src; 669 670 /* 671 * Source selection for ICMP replies: --- 52 unchanged lines hidden (view full) --- 724 * If the packet was transiting through us, use the address of 725 * the interface that is the closest to the packet source. 726 * When we don't have a route back to the packet source, stop here 727 * and drop the packet. 728 */ 729 ia = ip_rtaddr(ip->ip_dst, M_GETFIB(m)); 730 if (ia == NULL) { 731 m_freem(m); |
732 V_icmpstat.icps_noroute++; | 732 ICMPSTAT_INC(icps_noroute); |
733 goto done; 734 } 735match: 736#ifdef MAC 737 mac_netinet_icmp_replyinplace(m); 738#endif 739 t = IA_SIN(ia)->sin_addr; 740 ip->ip_src = t; --- 217 unchanged lines hidden --- | 733 goto done; 734 } 735match: 736#ifdef MAC 737 mac_netinet_icmp_replyinplace(m); 738#endif 739 t = IA_SIN(ia)->sin_addr; 740 ip->ip_src = t; --- 217 unchanged lines hidden --- |