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 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
| 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 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
|
34 * $FreeBSD: head/sys/netinet/ip_icmp.c 51282 1999-09-14 16:40:28Z des $
| 34 * $FreeBSD: head/sys/netinet/ip_icmp.c 55009 1999-12-22 19:13:38Z shin $
|
35 */ 36
| 35 */ 36
|
| 37#include "opt_ipsec.h" 38
|
37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/mbuf.h> 40#include <sys/protosw.h> 41#include <sys/socket.h> 42#include <sys/time.h> 43#include <sys/kernel.h> 44#include <sys/sysctl.h> 45 46#include <net/if.h> 47#include <net/route.h> 48 49#define _IP_VHL 50#include <netinet/in.h> 51#include <netinet/in_systm.h> 52#include <netinet/in_var.h> 53#include <netinet/ip.h> 54#include <netinet/ip_icmp.h> 55#include <netinet/ip_var.h> 56#include <netinet/icmp_var.h> 57
| 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/mbuf.h> 42#include <sys/protosw.h> 43#include <sys/socket.h> 44#include <sys/time.h> 45#include <sys/kernel.h> 46#include <sys/sysctl.h> 47 48#include <net/if.h> 49#include <net/route.h> 50 51#define _IP_VHL 52#include <netinet/in.h> 53#include <netinet/in_systm.h> 54#include <netinet/in_var.h> 55#include <netinet/ip.h> 56#include <netinet/ip_icmp.h> 57#include <netinet/ip_var.h> 58#include <netinet/icmp_var.h> 59
|
| 60#ifdef IPSEC 61#include <netinet6/ipsec.h> 62#include <netkey/key.h> 63#endif 64 65#include "faith.h" 66#if defined(NFAITH) && NFAITH > 0 67#include <net/if_types.h> 68#endif 69
|
58/* 59 * ICMP routines: error generation, receive packet processing, and 60 * routines to turnaround packets back to the originator, and 61 * host table maintenance routines. 62 */ 63 64static struct icmpstat icmpstat; 65SYSCTL_STRUCT(_net_inet_icmp, ICMPCTL_STATS, stats, CTLFLAG_RD, 66 &icmpstat, icmpstat, ""); 67 68static int icmpmaskrepl = 0; 69SYSCTL_INT(_net_inet_icmp, ICMPCTL_MASKREPL, maskrepl, CTLFLAG_RW, 70 &icmpmaskrepl, 0, ""); 71 72static int drop_redirect = 0; 73SYSCTL_INT(_net_inet_icmp, OID_AUTO, drop_redirect, CTLFLAG_RW, 74 &drop_redirect, 0, ""); 75 76static int log_redirect = 0; 77SYSCTL_INT(_net_inet_icmp, OID_AUTO, log_redirect, CTLFLAG_RW, 78 &log_redirect, 0, ""); 79 80#ifdef ICMP_BANDLIM 81 82/* 83 * ICMP error-response bandwidth limiting sysctl. If not enabled, sysctl 84 * variable content is -1 and read-only. 85 */ 86 87static int icmplim = 100; 88SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RW, 89 &icmplim, 0, ""); 90#else 91 92static int icmplim = -1; 93SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RD, 94 &icmplim, 0, ""); 95 96#endif 97 98/* 99 * ICMP broadcast echo sysctl 100 */ 101 102static int icmpbmcastecho = 0; 103SYSCTL_INT(_net_inet_icmp, OID_AUTO, bmcastecho, CTLFLAG_RW, 104 &icmpbmcastecho, 0, ""); 105 106 107#ifdef ICMPPRINTFS 108int icmpprintfs = 0; 109#endif 110 111static void icmp_reflect __P((struct mbuf *)); 112static void icmp_send __P((struct mbuf *, struct mbuf *)); 113static int ip_next_mtu __P((int, int)); 114 115extern struct protosw inetsw[]; 116 117/* 118 * Generate an error packet of type error 119 * in response to bad packet ip. 120 */ 121void 122icmp_error(n, type, code, dest, destifp) 123 struct mbuf *n; 124 int type, code; 125 n_long dest; 126 struct ifnet *destifp; 127{ 128 register struct ip *oip = mtod(n, struct ip *), *nip; 129 register unsigned oiplen = IP_VHL_HL(oip->ip_vhl) << 2; 130 register struct icmp *icp; 131 register struct mbuf *m; 132 unsigned icmplen; 133 134#ifdef ICMPPRINTFS 135 if (icmpprintfs) 136 printf("icmp_error(%p, %x, %d)\n", oip, type, code); 137#endif 138 if (type != ICMP_REDIRECT) 139 icmpstat.icps_error++; 140 /* 141 * Don't send error if not the first fragment of message. 142 * Don't error if the old packet protocol was ICMP 143 * error message, only known informational types. 144 */ 145 if (oip->ip_off &~ (IP_MF|IP_DF)) 146 goto freeit; 147 if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT && 148 n->m_len >= oiplen + ICMP_MINLEN && 149 !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiplen))->icmp_type)) { 150 icmpstat.icps_oldicmp++; 151 goto freeit; 152 } 153 /* Don't send error in response to a multicast or broadcast packet */ 154 if (n->m_flags & (M_BCAST|M_MCAST)) 155 goto freeit; 156 /* 157 * First, formulate icmp message 158 */ 159 m = m_gethdr(M_DONTWAIT, MT_HEADER); 160 if (m == NULL) 161 goto freeit; 162 icmplen = oiplen + min(8, oip->ip_len); 163 m->m_len = icmplen + ICMP_MINLEN; 164 MH_ALIGN(m, m->m_len); 165 icp = mtod(m, struct icmp *); 166 if ((u_int)type > ICMP_MAXTYPE) 167 panic("icmp_error"); 168 icmpstat.icps_outhist[type]++; 169 icp->icmp_type = type; 170 if (type == ICMP_REDIRECT) 171 icp->icmp_gwaddr.s_addr = dest; 172 else { 173 icp->icmp_void = 0; 174 /* 175 * The following assignments assume an overlay with the 176 * zeroed icmp_void field. 177 */ 178 if (type == ICMP_PARAMPROB) { 179 icp->icmp_pptr = code; 180 code = 0; 181 } else if (type == ICMP_UNREACH && 182 code == ICMP_UNREACH_NEEDFRAG && destifp) { 183 icp->icmp_nextmtu = htons(destifp->if_mtu); 184 } 185 } 186 187 icp->icmp_code = code; 188 bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, icmplen); 189 nip = &icp->icmp_ip; 190 nip->ip_len = htons((u_short)(nip->ip_len + oiplen)); 191 192 /* 193 * Now, copy old ip header (without options) 194 * in front of icmp message. 195 */ 196 if (m->m_data - sizeof(struct ip) < m->m_pktdat) 197 panic("icmp len"); 198 m->m_data -= sizeof(struct ip); 199 m->m_len += sizeof(struct ip); 200 m->m_pkthdr.len = m->m_len; 201 m->m_pkthdr.rcvif = n->m_pkthdr.rcvif; 202 nip = mtod(m, struct ip *); 203 bcopy((caddr_t)oip, (caddr_t)nip, sizeof(struct ip)); 204 nip->ip_len = m->m_len; 205 nip->ip_vhl = IP_VHL_BORING; 206 nip->ip_p = IPPROTO_ICMP; 207 nip->ip_tos = 0; 208 icmp_reflect(m); 209 210freeit: 211 m_freem(n); 212} 213 214static struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET }; 215static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET }; 216static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET }; 217 218/* 219 * Process a received ICMP message. 220 */ 221void
| 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_RD, 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 92#ifdef ICMP_BANDLIM 93 94/* 95 * ICMP error-response bandwidth limiting sysctl. If not enabled, sysctl 96 * variable content is -1 and read-only. 97 */ 98 99static int icmplim = 100; 100SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RW, 101 &icmplim, 0, ""); 102#else 103 104static int icmplim = -1; 105SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RD, 106 &icmplim, 0, ""); 107 108#endif 109 110/* 111 * ICMP broadcast echo sysctl 112 */ 113 114static int icmpbmcastecho = 0; 115SYSCTL_INT(_net_inet_icmp, OID_AUTO, bmcastecho, CTLFLAG_RW, 116 &icmpbmcastecho, 0, ""); 117 118 119#ifdef ICMPPRINTFS 120int icmpprintfs = 0; 121#endif 122 123static void icmp_reflect __P((struct mbuf *)); 124static void icmp_send __P((struct mbuf *, struct mbuf *)); 125static int ip_next_mtu __P((int, int)); 126 127extern struct protosw inetsw[]; 128 129/* 130 * Generate an error packet of type error 131 * in response to bad packet ip. 132 */ 133void 134icmp_error(n, type, code, dest, destifp) 135 struct mbuf *n; 136 int type, code; 137 n_long dest; 138 struct ifnet *destifp; 139{ 140 register struct ip *oip = mtod(n, struct ip *), *nip; 141 register unsigned oiplen = IP_VHL_HL(oip->ip_vhl) << 2; 142 register struct icmp *icp; 143 register struct mbuf *m; 144 unsigned icmplen; 145 146#ifdef ICMPPRINTFS 147 if (icmpprintfs) 148 printf("icmp_error(%p, %x, %d)\n", oip, type, code); 149#endif 150 if (type != ICMP_REDIRECT) 151 icmpstat.icps_error++; 152 /* 153 * Don't send error if not the first fragment of message. 154 * Don't error if the old packet protocol was ICMP 155 * error message, only known informational types. 156 */ 157 if (oip->ip_off &~ (IP_MF|IP_DF)) 158 goto freeit; 159 if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT && 160 n->m_len >= oiplen + ICMP_MINLEN && 161 !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiplen))->icmp_type)) { 162 icmpstat.icps_oldicmp++; 163 goto freeit; 164 } 165 /* Don't send error in response to a multicast or broadcast packet */ 166 if (n->m_flags & (M_BCAST|M_MCAST)) 167 goto freeit; 168 /* 169 * First, formulate icmp message 170 */ 171 m = m_gethdr(M_DONTWAIT, MT_HEADER); 172 if (m == NULL) 173 goto freeit; 174 icmplen = oiplen + min(8, oip->ip_len); 175 m->m_len = icmplen + ICMP_MINLEN; 176 MH_ALIGN(m, m->m_len); 177 icp = mtod(m, struct icmp *); 178 if ((u_int)type > ICMP_MAXTYPE) 179 panic("icmp_error"); 180 icmpstat.icps_outhist[type]++; 181 icp->icmp_type = type; 182 if (type == ICMP_REDIRECT) 183 icp->icmp_gwaddr.s_addr = dest; 184 else { 185 icp->icmp_void = 0; 186 /* 187 * The following assignments assume an overlay with the 188 * zeroed icmp_void field. 189 */ 190 if (type == ICMP_PARAMPROB) { 191 icp->icmp_pptr = code; 192 code = 0; 193 } else if (type == ICMP_UNREACH && 194 code == ICMP_UNREACH_NEEDFRAG && destifp) { 195 icp->icmp_nextmtu = htons(destifp->if_mtu); 196 } 197 } 198 199 icp->icmp_code = code; 200 bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, icmplen); 201 nip = &icp->icmp_ip; 202 nip->ip_len = htons((u_short)(nip->ip_len + oiplen)); 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
|
222icmp_input(m, hlen)
| 234icmp_input(m, off, proto)
|
223 register struct mbuf *m;
| 235 register struct mbuf *m;
|
224 int hlen;
| 236 int off, proto;
|
225{
| 237{
|
| 238 int hlen = off;
|
226 register struct icmp *icp; 227 register struct ip *ip = mtod(m, struct ip *); 228 int icmplen = ip->ip_len; 229 register int i; 230 struct in_ifaddr *ia; 231 void (*ctlfunc) __P((int, struct sockaddr *, void *)); 232 int code; 233 234 /* 235 * Locate icmp structure in mbuf, and check 236 * that not corrupted and of at least minimum length. 237 */ 238#ifdef ICMPPRINTFS 239 if (icmpprintfs) { 240 char buf[4 * sizeof "123"]; 241 strcpy(buf, inet_ntoa(ip->ip_src)); 242 printf("icmp_input from %s to %s, len %d\n", 243 buf, inet_ntoa(ip->ip_dst), icmplen); 244 } 245#endif 246 if (icmplen < ICMP_MINLEN) { 247 icmpstat.icps_tooshort++; 248 goto freeit; 249 } 250 i = hlen + min(icmplen, ICMP_ADVLENMIN); 251 if (m->m_len < i && (m = m_pullup(m, i)) == 0) { 252 icmpstat.icps_tooshort++; 253 return; 254 } 255 ip = mtod(m, struct ip *); 256 m->m_len -= hlen; 257 m->m_data += hlen; 258 icp = mtod(m, struct icmp *); 259 if (in_cksum(m, icmplen)) { 260 icmpstat.icps_checksum++; 261 goto freeit; 262 } 263 m->m_len += hlen; 264 m->m_data -= hlen; 265
| 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) __P((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 defined(NFAITH) && 0 < NFAITH 280 if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_type == IFT_FAITH) { 281 /* 282 * Deliver very specific ICMP type only. 283 */ 284 switch (icp->icmp_type) { 285 case ICMP_UNREACH: 286 case ICMP_TIMXCEED: 287 break; 288 default: 289 goto freeit; 290 } 291 } 292#endif 293
|
266#ifdef ICMPPRINTFS 267 if (icmpprintfs) 268 printf("icmp_input, type %d code %d\n", icp->icmp_type, 269 icp->icmp_code); 270#endif 271
| 294#ifdef ICMPPRINTFS 295 if (icmpprintfs) 296 printf("icmp_input, type %d code %d\n", icp->icmp_type, 297 icp->icmp_code); 298#endif 299
|
| 300#ifdef IPSEC 301 /* drop it if it does not match the policy */ 302 /* XXX Is there meaning of check in here ? */ 303 if (ipsec4_in_reject(m, NULL)) { 304 ipsecstat.in_polvio++; 305 goto freeit; 306 } 307#endif 308
|
272 /* 273 * Message type specific processing. 274 */ 275 if (icp->icmp_type > ICMP_MAXTYPE) 276 goto raw; 277 icmpstat.icps_inhist[icp->icmp_type]++; 278 code = icp->icmp_code; 279 switch (icp->icmp_type) { 280 281 case ICMP_UNREACH: 282 switch (code) { 283 case ICMP_UNREACH_NET: 284 case ICMP_UNREACH_HOST: 285 case ICMP_UNREACH_PROTOCOL: 286 case ICMP_UNREACH_PORT: 287 case ICMP_UNREACH_SRCFAIL: 288 code += PRC_UNREACH_NET; 289 break; 290 291 case ICMP_UNREACH_NEEDFRAG: 292 code = PRC_MSGSIZE; 293 break; 294 295 case ICMP_UNREACH_NET_UNKNOWN: 296 case ICMP_UNREACH_NET_PROHIB: 297 case ICMP_UNREACH_TOSNET: 298 code = PRC_UNREACH_NET; 299 break; 300 301 case ICMP_UNREACH_HOST_UNKNOWN: 302 case ICMP_UNREACH_ISOLATED: 303 case ICMP_UNREACH_HOST_PROHIB: 304 case ICMP_UNREACH_TOSHOST: 305 code = PRC_UNREACH_HOST; 306 break; 307 308 case ICMP_UNREACH_FILTER_PROHIB: 309 case ICMP_UNREACH_HOST_PRECEDENCE: 310 case ICMP_UNREACH_PRECEDENCE_CUTOFF: 311 code = PRC_UNREACH_PORT; 312 break; 313 314 default: 315 goto badcode; 316 } 317 goto deliver; 318 319 case ICMP_TIMXCEED: 320 if (code > 1) 321 goto badcode; 322 code += PRC_TIMXCEED_INTRANS; 323 goto deliver; 324 325 case ICMP_PARAMPROB: 326 if (code > 1) 327 goto badcode; 328 code = PRC_PARAMPROB; 329 goto deliver; 330 331 case ICMP_SOURCEQUENCH: 332 if (code) 333 goto badcode; 334 code = PRC_QUENCH; 335 deliver: 336 /* 337 * Problem with datagram; advise higher level routines. 338 */ 339 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || 340 IP_VHL_HL(icp->icmp_ip.ip_vhl) < (sizeof(struct ip) >> 2)) { 341 icmpstat.icps_badlen++; 342 goto freeit; 343 } 344 NTOHS(icp->icmp_ip.ip_len); 345 /* Discard ICMP's in response to multicast packets */ 346 if (IN_MULTICAST(ntohl(icp->icmp_ip.ip_dst.s_addr))) 347 goto badcode; 348#ifdef ICMPPRINTFS 349 if (icmpprintfs) 350 printf("deliver to protocol %d\n", icp->icmp_ip.ip_p); 351#endif 352 icmpsrc.sin_addr = icp->icmp_ip.ip_dst; 353#if 1 354 /* 355 * MTU discovery: 356 * If we got a needfrag and there is a host route to the 357 * original destination, and the MTU is not locked, then 358 * set the MTU in the route to the suggested new value 359 * (if given) and then notify as usual. The ULPs will 360 * notice that the MTU has changed and adapt accordingly. 361 * If no new MTU was suggested, then we guess a new one 362 * less than the current value. If the new MTU is 363 * unreasonably small (arbitrarily set at 296), then 364 * we reset the MTU to the interface value and enable the 365 * lock bit, indicating that we are no longer doing MTU 366 * discovery. 367 */ 368 if (code == PRC_MSGSIZE) { 369 struct rtentry *rt; 370 int mtu; 371 372 rt = rtalloc1((struct sockaddr *)&icmpsrc, 0, 373 RTF_CLONING | RTF_PRCLONING); 374 if (rt && (rt->rt_flags & RTF_HOST) 375 && !(rt->rt_rmx.rmx_locks & RTV_MTU)) { 376 mtu = ntohs(icp->icmp_nextmtu); 377 if (!mtu) 378 mtu = ip_next_mtu(rt->rt_rmx.rmx_mtu, 379 1); 380#ifdef DEBUG_MTUDISC 381 printf("MTU for %s reduced to %d\n", 382 inet_ntoa(icmpsrc.sin_addr), mtu); 383#endif 384 if (mtu < 296) { 385 /* rt->rt_rmx.rmx_mtu = 386 rt->rt_ifp->if_mtu; */ 387 rt->rt_rmx.rmx_locks |= RTV_MTU; 388 } else if (rt->rt_rmx.rmx_mtu > mtu) { 389 rt->rt_rmx.rmx_mtu = mtu; 390 } 391 } 392 if (rt) 393 RTFREE(rt); 394 } 395 396#endif
| 309 /* 310 * Message type specific processing. 311 */ 312 if (icp->icmp_type > ICMP_MAXTYPE) 313 goto raw; 314 icmpstat.icps_inhist[icp->icmp_type]++; 315 code = icp->icmp_code; 316 switch (icp->icmp_type) { 317 318 case ICMP_UNREACH: 319 switch (code) { 320 case ICMP_UNREACH_NET: 321 case ICMP_UNREACH_HOST: 322 case ICMP_UNREACH_PROTOCOL: 323 case ICMP_UNREACH_PORT: 324 case ICMP_UNREACH_SRCFAIL: 325 code += PRC_UNREACH_NET; 326 break; 327 328 case ICMP_UNREACH_NEEDFRAG: 329 code = PRC_MSGSIZE; 330 break; 331 332 case ICMP_UNREACH_NET_UNKNOWN: 333 case ICMP_UNREACH_NET_PROHIB: 334 case ICMP_UNREACH_TOSNET: 335 code = PRC_UNREACH_NET; 336 break; 337 338 case ICMP_UNREACH_HOST_UNKNOWN: 339 case ICMP_UNREACH_ISOLATED: 340 case ICMP_UNREACH_HOST_PROHIB: 341 case ICMP_UNREACH_TOSHOST: 342 code = PRC_UNREACH_HOST; 343 break; 344 345 case ICMP_UNREACH_FILTER_PROHIB: 346 case ICMP_UNREACH_HOST_PRECEDENCE: 347 case ICMP_UNREACH_PRECEDENCE_CUTOFF: 348 code = PRC_UNREACH_PORT; 349 break; 350 351 default: 352 goto badcode; 353 } 354 goto deliver; 355 356 case ICMP_TIMXCEED: 357 if (code > 1) 358 goto badcode; 359 code += PRC_TIMXCEED_INTRANS; 360 goto deliver; 361 362 case ICMP_PARAMPROB: 363 if (code > 1) 364 goto badcode; 365 code = PRC_PARAMPROB; 366 goto deliver; 367 368 case ICMP_SOURCEQUENCH: 369 if (code) 370 goto badcode; 371 code = PRC_QUENCH; 372 deliver: 373 /* 374 * Problem with datagram; advise higher level routines. 375 */ 376 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || 377 IP_VHL_HL(icp->icmp_ip.ip_vhl) < (sizeof(struct ip) >> 2)) { 378 icmpstat.icps_badlen++; 379 goto freeit; 380 } 381 NTOHS(icp->icmp_ip.ip_len); 382 /* Discard ICMP's in response to multicast packets */ 383 if (IN_MULTICAST(ntohl(icp->icmp_ip.ip_dst.s_addr))) 384 goto badcode; 385#ifdef ICMPPRINTFS 386 if (icmpprintfs) 387 printf("deliver to protocol %d\n", icp->icmp_ip.ip_p); 388#endif 389 icmpsrc.sin_addr = icp->icmp_ip.ip_dst; 390#if 1 391 /* 392 * MTU discovery: 393 * If we got a needfrag and there is a host route to the 394 * original destination, and the MTU is not locked, then 395 * set the MTU in the route to the suggested new value 396 * (if given) and then notify as usual. The ULPs will 397 * notice that the MTU has changed and adapt accordingly. 398 * If no new MTU was suggested, then we guess a new one 399 * less than the current value. If the new MTU is 400 * unreasonably small (arbitrarily set at 296), then 401 * we reset the MTU to the interface value and enable the 402 * lock bit, indicating that we are no longer doing MTU 403 * discovery. 404 */ 405 if (code == PRC_MSGSIZE) { 406 struct rtentry *rt; 407 int mtu; 408 409 rt = rtalloc1((struct sockaddr *)&icmpsrc, 0, 410 RTF_CLONING | RTF_PRCLONING); 411 if (rt && (rt->rt_flags & RTF_HOST) 412 && !(rt->rt_rmx.rmx_locks & RTV_MTU)) { 413 mtu = ntohs(icp->icmp_nextmtu); 414 if (!mtu) 415 mtu = ip_next_mtu(rt->rt_rmx.rmx_mtu, 416 1); 417#ifdef DEBUG_MTUDISC 418 printf("MTU for %s reduced to %d\n", 419 inet_ntoa(icmpsrc.sin_addr), mtu); 420#endif 421 if (mtu < 296) { 422 /* rt->rt_rmx.rmx_mtu = 423 rt->rt_ifp->if_mtu; */ 424 rt->rt_rmx.rmx_locks |= RTV_MTU; 425 } else if (rt->rt_rmx.rmx_mtu > mtu) { 426 rt->rt_rmx.rmx_mtu = mtu; 427 } 428 } 429 if (rt) 430 RTFREE(rt); 431 } 432 433#endif
|
| 434 /* 435 * XXX if the packet contains [IPv4 AH TCP], we can't make a 436 * notification to TCP layer. 437 */
|
397 ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput; 398 if (ctlfunc) 399 (*ctlfunc)(code, (struct sockaddr *)&icmpsrc, 400 (void *)&icp->icmp_ip); 401 break; 402 403 badcode: 404 icmpstat.icps_badcode++; 405 break; 406 407 case ICMP_ECHO: 408 if (!icmpbmcastecho 409 && (m->m_flags & (M_MCAST | M_BCAST)) != 0) { 410 icmpstat.icps_bmcastecho++; 411 break; 412 } 413 icp->icmp_type = ICMP_ECHOREPLY; 414 goto reflect; 415 416 case ICMP_TSTAMP: 417 if (!icmpbmcastecho 418 && (m->m_flags & (M_MCAST | M_BCAST)) != 0) { 419 icmpstat.icps_bmcasttstamp++; 420 break; 421 } 422 if (icmplen < ICMP_TSLEN) { 423 icmpstat.icps_badlen++; 424 break; 425 } 426 icp->icmp_type = ICMP_TSTAMPREPLY; 427 icp->icmp_rtime = iptime(); 428 icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */ 429 goto reflect; 430 431 case ICMP_MASKREQ: 432#define satosin(sa) ((struct sockaddr_in *)(sa)) 433 if (icmpmaskrepl == 0) 434 break; 435 /* 436 * We are not able to respond with all ones broadcast 437 * unless we receive it over a point-to-point interface. 438 */ 439 if (icmplen < ICMP_MASKLEN) 440 break; 441 switch (ip->ip_dst.s_addr) { 442 443 case INADDR_BROADCAST: 444 case INADDR_ANY: 445 icmpdst.sin_addr = ip->ip_src; 446 break; 447 448 default: 449 icmpdst.sin_addr = ip->ip_dst; 450 } 451 ia = (struct in_ifaddr *)ifaof_ifpforaddr( 452 (struct sockaddr *)&icmpdst, m->m_pkthdr.rcvif); 453 if (ia == 0) 454 break; 455 if (ia->ia_ifp == 0) 456 break; 457 icp->icmp_type = ICMP_MASKREPLY; 458 icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr; 459 if (ip->ip_src.s_addr == 0) { 460 if (ia->ia_ifp->if_flags & IFF_BROADCAST) 461 ip->ip_src = satosin(&ia->ia_broadaddr)->sin_addr; 462 else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT) 463 ip->ip_src = satosin(&ia->ia_dstaddr)->sin_addr; 464 } 465reflect: 466 ip->ip_len += hlen; /* since ip_input deducts this */ 467 icmpstat.icps_reflect++; 468 icmpstat.icps_outhist[icp->icmp_type]++; 469 icmp_reflect(m); 470 return; 471 472 case ICMP_REDIRECT: 473 if (log_redirect) { 474 u_long src, dst, gw; 475 476 src = ntohl(ip->ip_src.s_addr); 477 dst = ntohl(icp->icmp_ip.ip_dst.s_addr); 478 gw = ntohl(icp->icmp_gwaddr.s_addr); 479 printf("icmp redirect from %d.%d.%d.%d: " 480 "%d.%d.%d.%d => %d.%d.%d.%d\n", 481 (int)(src >> 24), (int)((src >> 16) & 0xff), 482 (int)((src >> 8) & 0xff), (int)(src & 0xff), 483 (int)(dst >> 24), (int)((dst >> 16) & 0xff), 484 (int)((dst >> 8) & 0xff), (int)(dst & 0xff), 485 (int)(gw >> 24), (int)((gw >> 16) & 0xff), 486 (int)((gw >> 8) & 0xff), (int)(gw & 0xff)); 487 } 488 if (drop_redirect) 489 break; 490 if (code > 3) 491 goto badcode; 492 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || 493 IP_VHL_HL(icp->icmp_ip.ip_vhl) < (sizeof(struct ip) >> 2)) { 494 icmpstat.icps_badlen++; 495 break; 496 } 497 /* 498 * Short circuit routing redirects to force 499 * immediate change in the kernel's routing 500 * tables. The message is also handed to anyone 501 * listening on a raw socket (e.g. the routing 502 * daemon for use in updating its tables). 503 */ 504 icmpgw.sin_addr = ip->ip_src; 505 icmpdst.sin_addr = icp->icmp_gwaddr; 506#ifdef ICMPPRINTFS 507 if (icmpprintfs) { 508 char buf[4 * sizeof "123"]; 509 strcpy(buf, inet_ntoa(icp->icmp_ip.ip_dst)); 510 511 printf("redirect dst %s to %s\n", 512 buf, inet_ntoa(icp->icmp_gwaddr)); 513 } 514#endif 515 icmpsrc.sin_addr = icp->icmp_ip.ip_dst; 516 rtredirect((struct sockaddr *)&icmpsrc, 517 (struct sockaddr *)&icmpdst, 518 (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST, 519 (struct sockaddr *)&icmpgw, (struct rtentry **)0); 520 pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&icmpsrc);
| 438 ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput; 439 if (ctlfunc) 440 (*ctlfunc)(code, (struct sockaddr *)&icmpsrc, 441 (void *)&icp->icmp_ip); 442 break; 443 444 badcode: 445 icmpstat.icps_badcode++; 446 break; 447 448 case ICMP_ECHO: 449 if (!icmpbmcastecho 450 && (m->m_flags & (M_MCAST | M_BCAST)) != 0) { 451 icmpstat.icps_bmcastecho++; 452 break; 453 } 454 icp->icmp_type = ICMP_ECHOREPLY; 455 goto reflect; 456 457 case ICMP_TSTAMP: 458 if (!icmpbmcastecho 459 && (m->m_flags & (M_MCAST | M_BCAST)) != 0) { 460 icmpstat.icps_bmcasttstamp++; 461 break; 462 } 463 if (icmplen < ICMP_TSLEN) { 464 icmpstat.icps_badlen++; 465 break; 466 } 467 icp->icmp_type = ICMP_TSTAMPREPLY; 468 icp->icmp_rtime = iptime(); 469 icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */ 470 goto reflect; 471 472 case ICMP_MASKREQ: 473#define satosin(sa) ((struct sockaddr_in *)(sa)) 474 if (icmpmaskrepl == 0) 475 break; 476 /* 477 * We are not able to respond with all ones broadcast 478 * unless we receive it over a point-to-point interface. 479 */ 480 if (icmplen < ICMP_MASKLEN) 481 break; 482 switch (ip->ip_dst.s_addr) { 483 484 case INADDR_BROADCAST: 485 case INADDR_ANY: 486 icmpdst.sin_addr = ip->ip_src; 487 break; 488 489 default: 490 icmpdst.sin_addr = ip->ip_dst; 491 } 492 ia = (struct in_ifaddr *)ifaof_ifpforaddr( 493 (struct sockaddr *)&icmpdst, m->m_pkthdr.rcvif); 494 if (ia == 0) 495 break; 496 if (ia->ia_ifp == 0) 497 break; 498 icp->icmp_type = ICMP_MASKREPLY; 499 icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr; 500 if (ip->ip_src.s_addr == 0) { 501 if (ia->ia_ifp->if_flags & IFF_BROADCAST) 502 ip->ip_src = satosin(&ia->ia_broadaddr)->sin_addr; 503 else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT) 504 ip->ip_src = satosin(&ia->ia_dstaddr)->sin_addr; 505 } 506reflect: 507 ip->ip_len += hlen; /* since ip_input deducts this */ 508 icmpstat.icps_reflect++; 509 icmpstat.icps_outhist[icp->icmp_type]++; 510 icmp_reflect(m); 511 return; 512 513 case ICMP_REDIRECT: 514 if (log_redirect) { 515 u_long src, dst, gw; 516 517 src = ntohl(ip->ip_src.s_addr); 518 dst = ntohl(icp->icmp_ip.ip_dst.s_addr); 519 gw = ntohl(icp->icmp_gwaddr.s_addr); 520 printf("icmp redirect from %d.%d.%d.%d: " 521 "%d.%d.%d.%d => %d.%d.%d.%d\n", 522 (int)(src >> 24), (int)((src >> 16) & 0xff), 523 (int)((src >> 8) & 0xff), (int)(src & 0xff), 524 (int)(dst >> 24), (int)((dst >> 16) & 0xff), 525 (int)((dst >> 8) & 0xff), (int)(dst & 0xff), 526 (int)(gw >> 24), (int)((gw >> 16) & 0xff), 527 (int)((gw >> 8) & 0xff), (int)(gw & 0xff)); 528 } 529 if (drop_redirect) 530 break; 531 if (code > 3) 532 goto badcode; 533 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || 534 IP_VHL_HL(icp->icmp_ip.ip_vhl) < (sizeof(struct ip) >> 2)) { 535 icmpstat.icps_badlen++; 536 break; 537 } 538 /* 539 * Short circuit routing redirects to force 540 * immediate change in the kernel's routing 541 * tables. The message is also handed to anyone 542 * listening on a raw socket (e.g. the routing 543 * daemon for use in updating its tables). 544 */ 545 icmpgw.sin_addr = ip->ip_src; 546 icmpdst.sin_addr = icp->icmp_gwaddr; 547#ifdef ICMPPRINTFS 548 if (icmpprintfs) { 549 char buf[4 * sizeof "123"]; 550 strcpy(buf, inet_ntoa(icp->icmp_ip.ip_dst)); 551 552 printf("redirect dst %s to %s\n", 553 buf, inet_ntoa(icp->icmp_gwaddr)); 554 } 555#endif 556 icmpsrc.sin_addr = icp->icmp_ip.ip_dst; 557 rtredirect((struct sockaddr *)&icmpsrc, 558 (struct sockaddr *)&icmpdst, 559 (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST, 560 (struct sockaddr *)&icmpgw, (struct rtentry **)0); 561 pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&icmpsrc);
|
| 562#ifdef IPSEC 563 key_sa_routechange((struct sockaddr *)&icmpsrc); 564#endif
|
521 break; 522 523 /* 524 * No kernel processing for the following; 525 * just fall through to send to raw listener. 526 */ 527 case ICMP_ECHOREPLY: 528 case ICMP_ROUTERADVERT: 529 case ICMP_ROUTERSOLICIT: 530 case ICMP_TSTAMPREPLY: 531 case ICMP_IREQREPLY: 532 case ICMP_MASKREPLY: 533 default: 534 break; 535 } 536 537raw:
| 565 break; 566 567 /* 568 * No kernel processing for the following; 569 * just fall through to send to raw listener. 570 */ 571 case ICMP_ECHOREPLY: 572 case ICMP_ROUTERADVERT: 573 case ICMP_ROUTERSOLICIT: 574 case ICMP_TSTAMPREPLY: 575 case ICMP_IREQREPLY: 576 case ICMP_MASKREPLY: 577 default: 578 break; 579 } 580 581raw:
|
538 rip_input(m, hlen);
| 582 rip_input(m, off, proto);
|
539 return; 540 541freeit: 542 m_freem(m); 543} 544 545/* 546 * Reflect the ip packet back to the source 547 */ 548static void 549icmp_reflect(m) 550 struct mbuf *m; 551{ 552 register struct ip *ip = mtod(m, struct ip *); 553 register struct in_ifaddr *ia; 554 struct in_addr t; 555 struct mbuf *opts = 0; 556 int optlen = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof(struct ip); 557 558 if (!in_canforward(ip->ip_src) && 559 ((ntohl(ip->ip_src.s_addr) & IN_CLASSA_NET) != 560 (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))) { 561 m_freem(m); /* Bad return address */ 562 goto done; /* Ip_output() will check for broadcast */ 563 } 564 t = ip->ip_dst; 565 ip->ip_dst = ip->ip_src; 566 /* 567 * If the incoming packet was addressed directly to us, 568 * use dst as the src for the reply. Otherwise (broadcast 569 * or anonymous), use the address which corresponds 570 * to the incoming interface. 571 */ 572 for (ia = in_ifaddrhead.tqh_first; ia; ia = ia->ia_link.tqe_next) { 573 if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr) 574 break; 575 if (ia->ia_ifp && (ia->ia_ifp->if_flags & IFF_BROADCAST) && 576 t.s_addr == satosin(&ia->ia_broadaddr)->sin_addr.s_addr) 577 break; 578 } 579 icmpdst.sin_addr = t; 580 if ((ia == (struct in_ifaddr *)0) && m->m_pkthdr.rcvif) 581 ia = (struct in_ifaddr *)ifaof_ifpforaddr( 582 (struct sockaddr *)&icmpdst, m->m_pkthdr.rcvif); 583 /* 584 * The following happens if the packet was not addressed to us, 585 * and was received on an interface with no IP address. 586 */ 587 if (ia == (struct in_ifaddr *)0) 588 ia = in_ifaddrhead.tqh_first; 589 t = IA_SIN(ia)->sin_addr; 590 ip->ip_src = t; 591 ip->ip_ttl = MAXTTL; 592 593 if (optlen > 0) { 594 register u_char *cp; 595 int opt, cnt; 596 u_int len; 597 598 /* 599 * Retrieve any source routing from the incoming packet; 600 * add on any record-route or timestamp options. 601 */ 602 cp = (u_char *) (ip + 1); 603 if ((opts = ip_srcroute()) == 0 && 604 (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) { 605 opts->m_len = sizeof(struct in_addr); 606 mtod(opts, struct in_addr *)->s_addr = 0; 607 } 608 if (opts) { 609#ifdef ICMPPRINTFS 610 if (icmpprintfs) 611 printf("icmp_reflect optlen %d rt %d => ", 612 optlen, opts->m_len); 613#endif 614 for (cnt = optlen; cnt > 0; cnt -= len, cp += len) { 615 opt = cp[IPOPT_OPTVAL]; 616 if (opt == IPOPT_EOL) 617 break; 618 if (opt == IPOPT_NOP) 619 len = 1; 620 else { 621 len = cp[IPOPT_OLEN]; 622 if (len <= 0 || len > cnt) 623 break; 624 } 625 /* 626 * Should check for overflow, but it "can't happen" 627 */ 628 if (opt == IPOPT_RR || opt == IPOPT_TS || 629 opt == IPOPT_SECURITY) { 630 bcopy((caddr_t)cp, 631 mtod(opts, caddr_t) + opts->m_len, len); 632 opts->m_len += len; 633 } 634 } 635 /* Terminate & pad, if necessary */ 636 cnt = opts->m_len % 4; 637 if (cnt) { 638 for (; cnt < 4; cnt++) { 639 *(mtod(opts, caddr_t) + opts->m_len) = 640 IPOPT_EOL; 641 opts->m_len++; 642 } 643 } 644#ifdef ICMPPRINTFS 645 if (icmpprintfs) 646 printf("%d\n", opts->m_len); 647#endif 648 } 649 /* 650 * Now strip out original options by copying rest of first 651 * mbuf's data back, and adjust the IP length. 652 */ 653 ip->ip_len -= optlen; 654 ip->ip_vhl = IP_VHL_BORING; 655 m->m_len -= optlen; 656 if (m->m_flags & M_PKTHDR) 657 m->m_pkthdr.len -= optlen; 658 optlen += sizeof(struct ip); 659 bcopy((caddr_t)ip + optlen, (caddr_t)(ip + 1), 660 (unsigned)(m->m_len - sizeof(struct ip))); 661 } 662 m->m_flags &= ~(M_BCAST|M_MCAST); 663 icmp_send(m, opts); 664done: 665 if (opts) 666 (void)m_free(opts); 667} 668 669/* 670 * Send an icmp packet back to the ip level, 671 * after supplying a checksum. 672 */ 673static void 674icmp_send(m, opts) 675 register struct mbuf *m; 676 struct mbuf *opts; 677{ 678 register struct ip *ip = mtod(m, struct ip *); 679 register int hlen; 680 register struct icmp *icp; 681 struct route ro; 682 683 hlen = IP_VHL_HL(ip->ip_vhl) << 2; 684 m->m_data += hlen; 685 m->m_len -= hlen; 686 icp = mtod(m, struct icmp *); 687 icp->icmp_cksum = 0; 688 icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen); 689 m->m_data -= hlen; 690 m->m_len += hlen; 691 m->m_pkthdr.rcvif = (struct ifnet *)0; 692#ifdef ICMPPRINTFS 693 if (icmpprintfs) { 694 char buf[4 * sizeof "123"]; 695 strcpy(buf, inet_ntoa(ip->ip_dst)); 696 printf("icmp_send dst %s src %s\n", 697 buf, inet_ntoa(ip->ip_src)); 698 } 699#endif 700 bzero(&ro, sizeof ro); 701 (void) ip_output(m, opts, &ro, 0, NULL); 702 if (ro.ro_rt) 703 RTFREE(ro.ro_rt); 704} 705 706n_time 707iptime() 708{ 709 struct timeval atv; 710 u_long t; 711 712 microtime(&atv); 713 t = (atv.tv_sec % (24*60*60)) * 1000 + atv.tv_usec / 1000; 714 return (htonl(t)); 715} 716 717#if 1 718/* 719 * Return the next larger or smaller MTU plateau (table from RFC 1191) 720 * given current value MTU. If DIR is less than zero, a larger plateau 721 * is returned; otherwise, a smaller value is returned. 722 */ 723static int 724ip_next_mtu(mtu, dir) 725 int mtu; 726 int dir; 727{ 728 static int mtutab[] = { 729 65535, 32000, 17914, 8166, 4352, 2002, 1492, 1006, 508, 296, 730 68, 0 731 }; 732 int i; 733 734 for (i = 0; i < (sizeof mtutab) / (sizeof mtutab[0]); i++) { 735 if (mtu >= mtutab[i]) 736 break; 737 } 738 739 if (dir < 0) { 740 if (i == 0) { 741 return 0; 742 } else { 743 return mtutab[i - 1]; 744 } 745 } else { 746 if (mtutab[i] == 0) { 747 return 0; 748 } else if(mtu > mtutab[i]) { 749 return mtutab[i]; 750 } else { 751 return mtutab[i + 1]; 752 } 753 } 754} 755#endif 756 757#ifdef ICMP_BANDLIM 758 759/* 760 * badport_bandlim() - check for ICMP bandwidth limit 761 * 762 * Return 0 if it is ok to send an ICMP error response, -1 if we have 763 * hit our bandwidth limit and it is not ok. 764 * 765 * If icmplim is <= 0, the feature is disabled and 0 is returned. 766 * 767 * For now we separate the TCP and UDP subsystems w/ different 'which' 768 * values. We may eventually remove this separation (and simplify the 769 * code further). 770 * 771 * Note that the printing of the error message is delayed so we can 772 * properly print the icmp error rate that the system was trying to do 773 * (i.e. 22000/100 pps, etc...). This can cause long delays in printing 774 * the 'final' error, but it doesn't make sense to solve the printing 775 * delay with more complex code. 776 */ 777 778int 779badport_bandlim(int which) 780{ 781 static int lticks[2]; 782 static int lpackets[2]; 783 int dticks; 784 785 /* 786 * Return ok status if feature disabled or argument out of 787 * ranage. 788 */ 789 790 if (icmplim <= 0 || which >= 2 || which < 0) 791 return(0); 792 dticks = ticks - lticks[which]; 793 794 /* 795 * reset stats when cumulative dt exceeds one second. 796 */ 797 798 if ((unsigned int)dticks > hz) { 799 if (lpackets[which] > icmplim) { 800 printf("icmp-response bandwidth limit %d/%d pps\n", 801 lpackets[which], 802 icmplim 803 ); 804 } 805 lticks[which] = ticks; 806 lpackets[which] = 0; 807 } 808 809 /* 810 * bump packet count 811 */ 812 813 if (++lpackets[which] > icmplim) { 814 return(-1); 815 } 816 return(0); 817} 818 819#endif 820 821
| 583 return; 584 585freeit: 586 m_freem(m); 587} 588 589/* 590 * Reflect the ip packet back to the source 591 */ 592static void 593icmp_reflect(m) 594 struct mbuf *m; 595{ 596 register struct ip *ip = mtod(m, struct ip *); 597 register struct in_ifaddr *ia; 598 struct in_addr t; 599 struct mbuf *opts = 0; 600 int optlen = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof(struct ip); 601 602 if (!in_canforward(ip->ip_src) && 603 ((ntohl(ip->ip_src.s_addr) & IN_CLASSA_NET) != 604 (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))) { 605 m_freem(m); /* Bad return address */ 606 goto done; /* Ip_output() will check for broadcast */ 607 } 608 t = ip->ip_dst; 609 ip->ip_dst = ip->ip_src; 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 for (ia = in_ifaddrhead.tqh_first; ia; ia = ia->ia_link.tqe_next) { 617 if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr) 618 break; 619 if (ia->ia_ifp && (ia->ia_ifp->if_flags & IFF_BROADCAST) && 620 t.s_addr == satosin(&ia->ia_broadaddr)->sin_addr.s_addr) 621 break; 622 } 623 icmpdst.sin_addr = t; 624 if ((ia == (struct in_ifaddr *)0) && m->m_pkthdr.rcvif) 625 ia = (struct in_ifaddr *)ifaof_ifpforaddr( 626 (struct sockaddr *)&icmpdst, m->m_pkthdr.rcvif); 627 /* 628 * The following happens if the packet was not addressed to us, 629 * and was received on an interface with no IP address. 630 */ 631 if (ia == (struct in_ifaddr *)0) 632 ia = in_ifaddrhead.tqh_first; 633 t = IA_SIN(ia)->sin_addr; 634 ip->ip_src = t; 635 ip->ip_ttl = MAXTTL; 636 637 if (optlen > 0) { 638 register u_char *cp; 639 int opt, cnt; 640 u_int len; 641 642 /* 643 * Retrieve any source routing from the incoming packet; 644 * add on any record-route or timestamp options. 645 */ 646 cp = (u_char *) (ip + 1); 647 if ((opts = ip_srcroute()) == 0 && 648 (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) { 649 opts->m_len = sizeof(struct in_addr); 650 mtod(opts, struct in_addr *)->s_addr = 0; 651 } 652 if (opts) { 653#ifdef ICMPPRINTFS 654 if (icmpprintfs) 655 printf("icmp_reflect optlen %d rt %d => ", 656 optlen, opts->m_len); 657#endif 658 for (cnt = optlen; cnt > 0; cnt -= len, cp += len) { 659 opt = cp[IPOPT_OPTVAL]; 660 if (opt == IPOPT_EOL) 661 break; 662 if (opt == IPOPT_NOP) 663 len = 1; 664 else { 665 len = cp[IPOPT_OLEN]; 666 if (len <= 0 || len > cnt) 667 break; 668 } 669 /* 670 * Should check for overflow, but it "can't happen" 671 */ 672 if (opt == IPOPT_RR || opt == IPOPT_TS || 673 opt == IPOPT_SECURITY) { 674 bcopy((caddr_t)cp, 675 mtod(opts, caddr_t) + opts->m_len, len); 676 opts->m_len += len; 677 } 678 } 679 /* Terminate & pad, if necessary */ 680 cnt = opts->m_len % 4; 681 if (cnt) { 682 for (; cnt < 4; cnt++) { 683 *(mtod(opts, caddr_t) + opts->m_len) = 684 IPOPT_EOL; 685 opts->m_len++; 686 } 687 } 688#ifdef ICMPPRINTFS 689 if (icmpprintfs) 690 printf("%d\n", opts->m_len); 691#endif 692 } 693 /* 694 * Now strip out original options by copying rest of first 695 * mbuf's data back, and adjust the IP length. 696 */ 697 ip->ip_len -= optlen; 698 ip->ip_vhl = IP_VHL_BORING; 699 m->m_len -= optlen; 700 if (m->m_flags & M_PKTHDR) 701 m->m_pkthdr.len -= optlen; 702 optlen += sizeof(struct ip); 703 bcopy((caddr_t)ip + optlen, (caddr_t)(ip + 1), 704 (unsigned)(m->m_len - sizeof(struct ip))); 705 } 706 m->m_flags &= ~(M_BCAST|M_MCAST); 707 icmp_send(m, opts); 708done: 709 if (opts) 710 (void)m_free(opts); 711} 712 713/* 714 * Send an icmp packet back to the ip level, 715 * after supplying a checksum. 716 */ 717static void 718icmp_send(m, opts) 719 register struct mbuf *m; 720 struct mbuf *opts; 721{ 722 register struct ip *ip = mtod(m, struct ip *); 723 register int hlen; 724 register struct icmp *icp; 725 struct route ro; 726 727 hlen = IP_VHL_HL(ip->ip_vhl) << 2; 728 m->m_data += hlen; 729 m->m_len -= hlen; 730 icp = mtod(m, struct icmp *); 731 icp->icmp_cksum = 0; 732 icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen); 733 m->m_data -= hlen; 734 m->m_len += hlen; 735 m->m_pkthdr.rcvif = (struct ifnet *)0; 736#ifdef ICMPPRINTFS 737 if (icmpprintfs) { 738 char buf[4 * sizeof "123"]; 739 strcpy(buf, inet_ntoa(ip->ip_dst)); 740 printf("icmp_send dst %s src %s\n", 741 buf, inet_ntoa(ip->ip_src)); 742 } 743#endif 744 bzero(&ro, sizeof ro); 745 (void) ip_output(m, opts, &ro, 0, NULL); 746 if (ro.ro_rt) 747 RTFREE(ro.ro_rt); 748} 749 750n_time 751iptime() 752{ 753 struct timeval atv; 754 u_long t; 755 756 microtime(&atv); 757 t = (atv.tv_sec % (24*60*60)) * 1000 + atv.tv_usec / 1000; 758 return (htonl(t)); 759} 760 761#if 1 762/* 763 * Return the next larger or smaller MTU plateau (table from RFC 1191) 764 * given current value MTU. If DIR is less than zero, a larger plateau 765 * is returned; otherwise, a smaller value is returned. 766 */ 767static int 768ip_next_mtu(mtu, dir) 769 int mtu; 770 int dir; 771{ 772 static int mtutab[] = { 773 65535, 32000, 17914, 8166, 4352, 2002, 1492, 1006, 508, 296, 774 68, 0 775 }; 776 int i; 777 778 for (i = 0; i < (sizeof mtutab) / (sizeof mtutab[0]); i++) { 779 if (mtu >= mtutab[i]) 780 break; 781 } 782 783 if (dir < 0) { 784 if (i == 0) { 785 return 0; 786 } else { 787 return mtutab[i - 1]; 788 } 789 } else { 790 if (mtutab[i] == 0) { 791 return 0; 792 } else if(mtu > mtutab[i]) { 793 return mtutab[i]; 794 } else { 795 return mtutab[i + 1]; 796 } 797 } 798} 799#endif 800 801#ifdef ICMP_BANDLIM 802 803/* 804 * badport_bandlim() - check for ICMP bandwidth limit 805 * 806 * Return 0 if it is ok to send an ICMP error response, -1 if we have 807 * hit our bandwidth limit and it is not ok. 808 * 809 * If icmplim is <= 0, the feature is disabled and 0 is returned. 810 * 811 * For now we separate the TCP and UDP subsystems w/ different 'which' 812 * values. We may eventually remove this separation (and simplify the 813 * code further). 814 * 815 * Note that the printing of the error message is delayed so we can 816 * properly print the icmp error rate that the system was trying to do 817 * (i.e. 22000/100 pps, etc...). This can cause long delays in printing 818 * the 'final' error, but it doesn't make sense to solve the printing 819 * delay with more complex code. 820 */ 821 822int 823badport_bandlim(int which) 824{ 825 static int lticks[2]; 826 static int lpackets[2]; 827 int dticks; 828 829 /* 830 * Return ok status if feature disabled or argument out of 831 * ranage. 832 */ 833 834 if (icmplim <= 0 || which >= 2 || which < 0) 835 return(0); 836 dticks = ticks - lticks[which]; 837 838 /* 839 * reset stats when cumulative dt exceeds one second. 840 */ 841 842 if ((unsigned int)dticks > hz) { 843 if (lpackets[which] > icmplim) { 844 printf("icmp-response bandwidth limit %d/%d pps\n", 845 lpackets[which], 846 icmplim 847 ); 848 } 849 lticks[which] = ticks; 850 lpackets[which] = 0; 851 } 852 853 /* 854 * bump packet count 855 */ 856 857 if (++lpackets[which] > icmplim) { 858 return(-1); 859 } 860 return(0); 861} 862 863#endif 864 865
|