4.4BSD snapshot (revision 8.1); add 1993 to copyright
[unix-history] / usr / src / sys / netinet / ip_icmp.c
CommitLineData
8ae0e4b4 1/*
e7a3707f
KB
2 * Copyright (c) 1982, 1986, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
8ae0e4b4 4 *
dbf0c423 5 * %sccs.include.redist.c%
2b6b6284 6 *
e7a3707f 7 * @(#)ip_icmp.c 8.1 (Berkeley) %G%
8ae0e4b4 8 */
81a36a8d 9
5548a02f
KB
10#include <sys/param.h>
11#include <sys/systm.h>
12#include <sys/malloc.h>
13#include <sys/mbuf.h>
14#include <sys/protosw.h>
15#include <sys/socket.h>
16#include <sys/time.h>
17#include <sys/kernel.h>
6e7edb25 18
5548a02f 19#include <net/if.h>
c46785cb 20#include <net/route.h>
f4d55810 21
5548a02f
KB
22#include <netinet/in.h>
23#include <netinet/in_systm.h>
24#include <netinet/in_var.h>
25#include <netinet/ip.h>
26#include <netinet/ip_icmp.h>
27#include <netinet/icmp_var.h>
81a36a8d
BJ
28
29/*
30 * ICMP routines: error generation, receive packet processing, and
31 * routines to turnaround packets back to the originator, and
32 * host table maintenance routines.
33 */
8f6ff0ef
KM
34
35int icmpmaskrepl = 0;
7a372964 36#ifdef ICMPPRINTFS
67387c9c 37int icmpprintfs = 0;
a60889ab 38#endif
81a36a8d 39
af58179c
MK
40extern struct protosw inetsw[];
41
81a36a8d 42/*
72e4f44e
SL
43 * Generate an error packet of type error
44 * in response to bad packet ip.
81a36a8d 45 */
d99f1c28 46void
69d96ae2 47icmp_error(n, type, code, dest, destifp)
9d91b170 48 struct mbuf *n;
755d8841 49 int type, code;
d99f1c28 50 n_long dest;
69d96ae2 51 struct ifnet *destifp;
81a36a8d 52{
9d91b170 53 register struct ip *oip = mtod(n, struct ip *), *nip;
72e4f44e
SL
54 register unsigned oiplen = oip->ip_hl << 2;
55 register struct icmp *icp;
9d91b170 56 register struct mbuf *m;
8011f5df 57 unsigned icmplen;
81a36a8d 58
a60889ab 59#ifdef ICMPPRINTFS
39674d5f
SL
60 if (icmpprintfs)
61 printf("icmp_error(%x, %d, %d)\n", oip, type, code);
a60889ab 62#endif
cd86d39a
MK
63 if (type != ICMP_REDIRECT)
64 icmpstat.icps_error++;
81a36a8d 65 /*
f22d98c3 66 * Don't send error if not the first fragment of message.
99fca325
MK
67 * Don't error if the old packet protocol was ICMP
68 * error message, only known informational types.
81a36a8d 69 */
f22d98c3 70 if (oip->ip_off &~ (IP_MF|IP_DF))
b4dc7708 71 goto freeit;
99fca325 72 if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT &&
0ebd7d37 73 dtom(oip)->m_len >= oiplen + ICMP_MINLEN &&
9a63a2be 74 n->m_len >= oiplen + ICMP_MINLEN &&
99fca325 75 !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiplen))->icmp_type)) {
7b66c1fd 76 icmpstat.icps_oldicmp++;
b4dc7708 77 goto freeit;
7b66c1fd 78 }
d6fa15c2 79 /* Don't send error in response to a multicast or broadcast packet */
09ed489e 80 if (n->m_flags & (M_BCAST|M_MCAST))
d6fa15c2 81 goto freeit;
81a36a8d 82 /*
72e4f44e 83 * First, formulate icmp message
81a36a8d 84 */
9d91b170 85 m = m_gethdr(M_DONTWAIT, MT_HEADER);
7b66c1fd 86 if (m == NULL)
b4dc7708 87 goto freeit;
9d91b170 88 icmplen = oiplen + min(8, oip->ip_len);
f22d98c3 89 m->m_len = icmplen + ICMP_MINLEN;
9d91b170 90 MH_ALIGN(m, m->m_len);
72e4f44e 91 icp = mtod(m, struct icmp *);
f22d98c3 92 if ((u_int)type > ICMP_MAXTYPE)
7b66c1fd
SL
93 panic("icmp_error");
94 icmpstat.icps_outhist[type]++;
81a36a8d 95 icp->icmp_type = type;
f22d98c3 96 if (type == ICMP_REDIRECT)
d99f1c28 97 icp->icmp_gwaddr.s_addr = dest;
69d96ae2 98 else {
f22d98c3 99 icp->icmp_void = 0;
69d96ae2
AC
100 /*
101 * The following assignments assume an overlay with the
102 * zeroed icmp_void field.
103 */
104 if (type == ICMP_PARAMPROB) {
105 icp->icmp_pptr = code;
106 code = 0;
107 } else if (type == ICMP_UNREACH &&
108 code == ICMP_UNREACH_NEEDFRAG && destifp) {
109 icp->icmp_nextmtu = htons(destifp->if_mtu);
110 }
72e4f44e 111 }
69d96ae2 112
72e4f44e 113 icp->icmp_code = code;
f22d98c3 114 bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, icmplen);
39674d5f 115 nip = &icp->icmp_ip;
9d91b170 116 nip->ip_len = htons((u_short)(nip->ip_len + oiplen));
81a36a8d
BJ
117
118 /*
9a63a2be
MK
119 * Now, copy old ip header (without options)
120 * in front of icmp message.
81a36a8d 121 */
9a63a2be 122 if (m->m_data - sizeof(struct ip) < m->m_pktdat)
f22d98c3 123 panic("icmp len");
9a63a2be
MK
124 m->m_data -= sizeof(struct ip);
125 m->m_len += sizeof(struct ip);
9d91b170
MK
126 m->m_pkthdr.len = m->m_len;
127 m->m_pkthdr.rcvif = n->m_pkthdr.rcvif;
72e4f44e 128 nip = mtod(m, struct ip *);
69d96ae2 129 bcopy((caddr_t)oip, (caddr_t)nip, sizeof(struct ip));
76a1d7bb 130 nip->ip_len = m->m_len;
9a63a2be 131 nip->ip_hl = sizeof(struct ip) >> 2;
0ebd7d37 132 nip->ip_hl = sizeof(struct ip) >> 2;
72e4f44e 133 nip->ip_p = IPPROTO_ICMP;
69d96ae2 134 nip->ip_tos = 0;
9d91b170 135 icmp_reflect(m);
81a36a8d 136
b4dc7708 137freeit:
9d91b170 138 m_freem(n);
81a36a8d
BJ
139}
140
72e4f44e 141static struct sockproto icmproto = { AF_INET, IPPROTO_ICMP };
9a63a2be
MK
142static struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET };
143static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET };
144static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET };
145struct sockaddr_in icmpmask = { 8, 0 };
72e4f44e 146
81a36a8d 147/*
d52566dd 148 * Process a received ICMP message.
81a36a8d 149 */
c46785cb 150void
9d91b170 151icmp_input(m, hlen)
166e6158 152 register struct mbuf *m;
9d91b170 153 int hlen;
81a36a8d 154{
81a36a8d 155 register struct icmp *icp;
d52566dd 156 register struct ip *ip = mtod(m, struct ip *);
9d91b170 157 int icmplen = ip->ip_len;
8046f415 158 register int i;
f22d98c3 159 struct in_ifaddr *ia;
c46785cb
KB
160 void (*ctlfunc) __P((int, struct sockaddr *, struct ip *));
161 int code;
b454c3ea 162 extern u_char ip_protox[];
81a36a8d
BJ
163
164 /*
165 * Locate icmp structure in mbuf, and check
166 * that not corrupted and of at least minimum length.
167 */
a60889ab 168#ifdef ICMPPRINTFS
39674d5f 169 if (icmpprintfs)
09ed489e
KS
170 printf("icmp_input from %x to %x, len %d\n",
171 ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr),
172 icmplen);
a60889ab 173#endif
4d75f980 174 if (icmplen < ICMP_MINLEN) {
7b66c1fd 175 icmpstat.icps_tooshort++;
b4dc7708 176 goto freeit;
7b66c1fd 177 }
479c0df7 178 i = hlen + min(icmplen, ICMP_ADVLENMIN);
d6fa15c2 179 if (m->m_len < i && (m = m_pullup(m, i)) == 0) {
167351c2
MK
180 icmpstat.icps_tooshort++;
181 return;
182 }
d6fa15c2 183 ip = mtod(m, struct ip *);
81a36a8d 184 m->m_len -= hlen;
9d91b170 185 m->m_data += hlen;
72e4f44e 186 icp = mtod(m, struct icmp *);
8046f415 187 if (in_cksum(m, icmplen)) {
7b66c1fd 188 icmpstat.icps_checksum++;
b4dc7708 189 goto freeit;
72e4f44e 190 }
76a1d7bb 191 m->m_len += hlen;
9d91b170 192 m->m_data -= hlen;
81a36a8d 193
a60889ab 194#ifdef ICMPPRINTFS
81a36a8d
BJ
195 /*
196 * Message type specific processing.
197 */
39674d5f
SL
198 if (icmpprintfs)
199 printf("icmp_input, type %d code %d\n", icp->icmp_type,
a60889ab
KM
200 icp->icmp_code);
201#endif
f22d98c3 202 if (icp->icmp_type > ICMP_MAXTYPE)
166e6158 203 goto raw;
7b66c1fd 204 icmpstat.icps_inhist[icp->icmp_type]++;
a60889ab 205 code = icp->icmp_code;
7b66c1fd 206 switch (icp->icmp_type) {
81a36a8d
BJ
207
208 case ICMP_UNREACH:
69d96ae2
AC
209 switch (code) {
210 case ICMP_UNREACH_NET:
211 case ICMP_UNREACH_HOST:
212 case ICMP_UNREACH_PROTOCOL:
213 case ICMP_UNREACH_PORT:
214 case ICMP_UNREACH_SRCFAIL:
215 code += PRC_UNREACH_NET;
216 break;
217
218 case ICMP_UNREACH_NEEDFRAG:
219 code = PRC_MSGSIZE;
220 break;
221
222 case ICMP_UNREACH_NET_UNKNOWN:
223 case ICMP_UNREACH_NET_PROHIB:
224 case ICMP_UNREACH_TOSNET:
225 code = PRC_UNREACH_NET;
226 break;
227
228 case ICMP_UNREACH_HOST_UNKNOWN:
229 case ICMP_UNREACH_ISOLATED:
230 case ICMP_UNREACH_HOST_PROHIB:
231 case ICMP_UNREACH_TOSHOST:
232 code = PRC_UNREACH_HOST;
233 break;
234
235 default:
236 goto badcode;
237 }
a60889ab
KM
238 goto deliver;
239
81a36a8d 240 case ICMP_TIMXCEED:
a60889ab
KM
241 if (code > 1)
242 goto badcode;
243 code += PRC_TIMXCEED_INTRANS;
244 goto deliver;
245
81a36a8d 246 case ICMP_PARAMPROB:
69d96ae2 247 if (code > 1)
a60889ab
KM
248 goto badcode;
249 code = PRC_PARAMPROB;
250 goto deliver;
251
72e4f44e 252 case ICMP_SOURCEQUENCH:
a60889ab
KM
253 if (code)
254 goto badcode;
255 code = PRC_QUENCH;
256 deliver:
81a36a8d 257 /*
a60889ab 258 * Problem with datagram; advise higher level routines.
81a36a8d 259 */
3953bf11
MK
260 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
261 icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) {
7b66c1fd 262 icmpstat.icps_badlen++;
b4dc7708 263 goto freeit;
7b66c1fd 264 }
3953bf11 265 NTOHS(icp->icmp_ip.ip_len);
a60889ab 266#ifdef ICMPPRINTFS
39674d5f
SL
267 if (icmpprintfs)
268 printf("deliver to protocol %d\n", icp->icmp_ip.ip_p);
a60889ab 269#endif
f22d98c3 270 icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
59965020 271 if (ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput)
3953bf11 272 (*ctlfunc)(code, (struct sockaddr *)&icmpsrc,
c46785cb 273 &icp->icmp_ip);
76a1d7bb 274 break;
a60889ab
KM
275
276 badcode:
277 icmpstat.icps_badcode++;
76a1d7bb 278 break;
81a36a8d
BJ
279
280 case ICMP_ECHO:
281 icp->icmp_type = ICMP_ECHOREPLY;
282 goto reflect;
283
284 case ICMP_TSTAMP:
7b66c1fd
SL
285 if (icmplen < ICMP_TSLEN) {
286 icmpstat.icps_badlen++;
76a1d7bb 287 break;
7b66c1fd 288 }
81a36a8d 289 icp->icmp_type = ICMP_TSTAMPREPLY;
2b4b57cd 290 icp->icmp_rtime = iptime();
81a36a8d
BJ
291 icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */
292 goto reflect;
293
09ed489e 294 case ICMP_MASKREQ:
c175a1bd 295#define satosin(sa) ((struct sockaddr_in *)(sa))
8f6ff0ef
KM
296 if (icmpmaskrepl == 0)
297 break;
09ed489e
KS
298 /*
299 * We are not able to respond with all ones broadcast
300 * unless we receive it over a point-to-point interface.
301 */
302 if (icmplen < ICMP_MASKLEN)
303 break;
304 switch (ip->ip_dst.s_addr) {
81a36a8d 305
09ed489e
KS
306 case INADDR_BROADCAST:
307 case INADDR_ANY:
308 icmpdst.sin_addr = ip->ip_src;
309 break;
310
311 default:
312 icmpdst.sin_addr = ip->ip_dst;
313 }
314 ia = (struct in_ifaddr *)ifaof_ifpforaddr(
315 (struct sockaddr *)&icmpdst, m->m_pkthdr.rcvif);
316 if (ia == 0)
76a1d7bb 317 break;
9b8941dc 318 icp->icmp_type = ICMP_MASKREPLY;
9a63a2be 319 icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr;
f22d98c3
MK
320 if (ip->ip_src.s_addr == 0) {
321 if (ia->ia_ifp->if_flags & IFF_BROADCAST)
322 ip->ip_src = satosin(&ia->ia_broadaddr)->sin_addr;
323 else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT)
324 ip->ip_src = satosin(&ia->ia_dstaddr)->sin_addr;
325 }
76a1d7bb
MK
326reflect:
327 ip->ip_len += hlen; /* since ip_input deducts this */
328 icmpstat.icps_reflect++;
329 icmpstat.icps_outhist[icp->icmp_type]++;
9d91b170 330 icmp_reflect(m);
76a1d7bb 331 return;
f22d98c3 332
a469458a 333 case ICMP_REDIRECT:
69d96ae2
AC
334 if (code > 3)
335 goto badcode;
336 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
337 icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) {
338 icmpstat.icps_badlen++;
339 break;
340 }
a469458a
SL
341 /*
342 * Short circuit routing redirects to force
343 * immediate change in the kernel's routing
344 * tables. The message is also handed to anyone
345 * listening on a raw socket (e.g. the routing
fbc81152 346 * daemon for use in updating its tables).
a469458a 347 */
f22d98c3 348 icmpgw.sin_addr = ip->ip_src;
167351c2 349 icmpdst.sin_addr = icp->icmp_gwaddr;
f22d98c3
MK
350#ifdef ICMPPRINTFS
351 if (icmpprintfs)
352 printf("redirect dst %x to %x\n", icp->icmp_ip.ip_dst,
353 icp->icmp_gwaddr);
354#endif
09ed489e
KS
355 icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
356 rtredirect((struct sockaddr *)&icmpsrc,
357 (struct sockaddr *)&icmpdst,
358 (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST,
359 (struct sockaddr *)&icmpgw, (struct rtentry **)0);
360 pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&icmpsrc);
76a1d7bb 361 break;
167351c2 362
76a1d7bb
MK
363 /*
364 * No kernel processing for the following;
365 * just fall through to send to raw listener.
366 */
167351c2 367 case ICMP_ECHOREPLY:
69d96ae2
AC
368 case ICMP_ROUTERADVERT:
369 case ICMP_ROUTERSOLICIT:
167351c2
MK
370 case ICMP_TSTAMPREPLY:
371 case ICMP_IREQREPLY:
f22d98c3 372 case ICMP_MASKREPLY:
81a36a8d 373 default:
76a1d7bb 374 break;
81a36a8d 375 }
76a1d7bb 376
166e6158 377raw:
d6fa15c2 378 rip_input(m);
af8f6a21 379 return;
76a1d7bb 380
b4dc7708 381freeit:
76a1d7bb 382 m_freem(m);
81a36a8d
BJ
383}
384
385/*
386 * Reflect the ip packet back to the source
387 */
c46785cb 388void
9d91b170
MK
389icmp_reflect(m)
390 struct mbuf *m;
81a36a8d 391{
9d91b170 392 register struct ip *ip = mtod(m, struct ip *);
c175a1bd 393 register struct in_ifaddr *ia;
f22d98c3 394 struct in_addr t;
5ba846a2 395 struct mbuf *opts = 0, *ip_srcroute();
76a1d7bb 396 int optlen = (ip->ip_hl << 2) - sizeof(struct ip);
81a36a8d 397
09ed489e
KS
398 if (!in_canforward(ip->ip_src) &&
399 ((ntohl(ip->ip_src.s_addr) & IN_CLASSA_NET) !=
400 (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))) {
401 m_freem(m); /* Bad return address */
402 goto done; /* Ip_output() will check for broadcast */
403 }
72e4f44e
SL
404 t = ip->ip_dst;
405 ip->ip_dst = ip->ip_src;
f22d98c3
MK
406 /*
407 * If the incoming packet was addressed directly to us,
408 * use dst as the src for the reply. Otherwise (broadcast
409 * or anonymous), use the address which corresponds
410 * to the incoming interface.
411 */
412 for (ia = in_ifaddr; ia; ia = ia->ia_next) {
413 if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr)
414 break;
415 if ((ia->ia_ifp->if_flags & IFF_BROADCAST) &&
416 t.s_addr == satosin(&ia->ia_broadaddr)->sin_addr.s_addr)
417 break;
418 }
09ed489e 419 icmpdst.sin_addr = t;
f22d98c3 420 if (ia == (struct in_ifaddr *)0)
09ed489e
KS
421 ia = (struct in_ifaddr *)ifaof_ifpforaddr(
422 (struct sockaddr *)&icmpdst, m->m_pkthdr.rcvif);
423 /*
424 * The following happens if the packet was not addressed to us,
425 * and was received on an interface with no IP address.
426 */
76751082
MK
427 if (ia == (struct in_ifaddr *)0)
428 ia = in_ifaddr;
429 t = IA_SIN(ia)->sin_addr;
72e4f44e 430 ip->ip_src = t;
2bc7b126 431 ip->ip_ttl = MAXTTL;
f22d98c3 432
76a1d7bb 433 if (optlen > 0) {
9a63a2be 434 register u_char *cp;
89369b13 435 struct mbuf *m = dtom(ip);
9a63a2be
MK
436 int opt, cnt, off;
437 u_int len;
438
0ebd7d37 439 register u_char *cp;
b4dc7708 440 int opt, cnt;
0ebd7d37
MK
441 u_int len;
442
cd86d39a 443 /*
9a63a2be
MK
444 * Retrieve any source routing from the incoming packet;
445 * add on any record-route or timestamp options.
cd86d39a 446 */
9a63a2be 447 cp = (u_char *) (ip + 1);
7a372964
MK
448 if ((opts = ip_srcroute()) == 0 &&
449 (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) {
450 opts->m_len = sizeof(struct in_addr);
451 mtod(opts, struct in_addr *)->s_addr = 0;
452 }
453 if (opts) {
454#ifdef ICMPPRINTFS
455 if (icmpprintfs)
456 printf("icmp_reflect optlen %d rt %d => ",
457 optlen, opts->m_len);
458#endif
9a63a2be 459 for (cnt = optlen; cnt > 0; cnt -= len, cp += len) {
7a372964
MK
460 opt = cp[IPOPT_OPTVAL];
461 if (opt == IPOPT_EOL)
462 break;
463 if (opt == IPOPT_NOP)
464 len = 1;
465 else {
466 len = cp[IPOPT_OLEN];
467 if (len <= 0 || len > cnt)
468 break;
469 }
470 /*
69d96ae2 471 * Should check for overflow, but it "can't happen"
7a372964 472 */
69d96ae2
AC
473 if (opt == IPOPT_RR || opt == IPOPT_TS ||
474 opt == IPOPT_SECURITY) {
7a372964
MK
475 bcopy((caddr_t)cp,
476 mtod(opts, caddr_t) + opts->m_len, len);
477 opts->m_len += len;
478 }
479 }
69d96ae2
AC
480 /* Terminate & pad, if necessary */
481 if (cnt = opts->m_len % 4) {
482 for (; cnt < 4; cnt++) {
483 *(mtod(opts, caddr_t) + opts->m_len) =
484 IPOPT_EOL;
485 opts->m_len++;
486 }
7a372964
MK
487 }
488#ifdef ICMPPRINTFS
489 if (icmpprintfs)
490 printf("%d\n", opts->m_len);
491#endif
9a63a2be 492 }
7a372964
MK
493 /*
494 * Now strip out original options by copying rest of first
495 * mbuf's data back, and adjust the IP length.
496 */
9a63a2be
MK
497 ip->ip_len -= optlen;
498 ip->ip_hl = sizeof(struct ip) >> 2;
7a372964 499 m->m_len -= optlen;
9d91b170
MK
500 if (m->m_flags & M_PKTHDR)
501 m->m_pkthdr.len -= optlen;
7a372964
MK
502 optlen += sizeof(struct ip);
503 bcopy((caddr_t)ip + optlen, (caddr_t)(ip + 1),
b4dc7708 504 (unsigned)(m->m_len - sizeof(struct ip)));
f22d98c3 505 }
6e132662 506 m->m_flags &= ~(M_BCAST|M_MCAST);
424b2707 507
9d91b170 508 icmp_send(m, opts);
09ed489e 509done:
cd86d39a 510 if (opts)
8011f5df 511 (void)m_free(opts);
81a36a8d
BJ
512}
513
514/*
72e4f44e
SL
515 * Send an icmp packet back to the ip level,
516 * after supplying a checksum.
81a36a8d 517 */
c46785cb 518void
9d91b170
MK
519icmp_send(m, opts)
520 register struct mbuf *m;
cd86d39a 521 struct mbuf *opts;
81a36a8d 522{
9d91b170 523 register struct ip *ip = mtod(m, struct ip *);
af8f6a21 524 register int hlen;
72e4f44e 525 register struct icmp *icp;
d52566dd 526
af8f6a21 527 hlen = ip->ip_hl << 2;
9d91b170 528 m->m_data += hlen;
76a1d7bb 529 m->m_len -= hlen;
72e4f44e
SL
530 icp = mtod(m, struct icmp *);
531 icp->icmp_cksum = 0;
532 icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen);
9d91b170 533 m->m_data -= hlen;
72e4f44e 534 m->m_len += hlen;
a60889ab 535#ifdef ICMPPRINTFS
39674d5f
SL
536 if (icmpprintfs)
537 printf("icmp_send dst %x src %x\n", ip->ip_dst, ip->ip_src);
a60889ab 538#endif
c46785cb 539 (void) ip_output(m, opts, NULL, 0, NULL);
d52566dd
BJ
540}
541
cdad2eb1 542n_time
2b4b57cd 543iptime()
d52566dd 544{
b3f3ec92 545 struct timeval atv;
2752c877 546 u_long t;
d52566dd 547
b3f3ec92
MK
548 microtime(&atv);
549 t = (atv.tv_sec % (24*60*60)) * 1000 + atv.tv_usec / 1000;
cdad2eb1 550 return (htonl(t));
d52566dd 551}
8f6ff0ef 552
c46785cb 553int
8f6ff0ef
KM
554icmp_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
555 int *name;
556 u_int namelen;
557 void *oldp;
558 size_t *oldlenp;
559 void *newp;
560 size_t newlen;
561{
562 extern int ip_ttl;
563
564 /* all sysctl names at this level are terminal */
565 if (namelen != 1)
566 return (ENOTDIR);
567
568 switch (name[0]) {
569 case ICMPCTL_MASKREPL:
570 return (sysctl_int(oldp, oldlenp, newp, newlen, &icmpmaskrepl));
571 default:
572 return (ENOPROTOOPT);
573 }
574 /* NOTREACHED */
575}