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