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