|
Lines 165-170
Link Here
|
| 165 |
int mtu; |
165 |
int mtu; |
| 166 |
struct m_tag *fwd_tag = NULL; |
166 |
struct m_tag *fwd_tag = NULL; |
| 167 |
|
167 |
|
|
|
168 |
struct mbuf *mcopy; |
| 169 |
|
| 168 |
/* |
170 |
/* |
| 169 |
* Are we active and forwarding packets? |
171 |
* Are we active and forwarding packets? |
| 170 |
*/ |
172 |
*/ |
|
Lines 230-235
Link Here
|
| 230 |
IPSTAT_INC(ips_total); |
232 |
IPSTAT_INC(ips_total); |
| 231 |
|
233 |
|
| 232 |
/* |
234 |
/* |
|
|
235 |
* Save the IP header and at most 8 bytes of the payload, |
| 236 |
* in case we need to generate an ICMP message to the src. |
| 237 |
* |
| 238 |
* XXX this can be optimized a lot by saving the data in a local |
| 239 |
* buffer on the stack (72 bytes at most), and only allocating the |
| 240 |
* mbuf if really necessary. The vast majority of the packets |
| 241 |
* are forwarded without having to send an ICMP back (either |
| 242 |
* because unnecessary, or because rate limited), so we are |
| 243 |
* really we are wasting a lot of work here. |
| 244 |
* |
| 245 |
* We don't use m_copy() because it might return a reference |
| 246 |
* to a shared cluster. Both this function and ip_output() |
| 247 |
* assume exclusive access to the IP header in `m', so any |
| 248 |
* data in a cluster may change before we reach icmp_error(). |
| 249 |
*/ |
| 250 |
mcopy = m_gethdr(M_NOWAIT, m->m_type); |
| 251 |
if (mcopy != NULL && !m_dup_pkthdr(mcopy, m, M_NOWAIT)) { |
| 252 |
/* |
| 253 |
* It's probably ok if the pkthdr dup fails (because |
| 254 |
* the deep copy of the tag chain failed), but for now |
| 255 |
* be conservative and just discard the copy since |
| 256 |
* code below may some day want the tags. |
| 257 |
*/ |
| 258 |
m_free(mcopy); |
| 259 |
mcopy = NULL; |
| 260 |
} |
| 261 |
if (mcopy != NULL) { |
| 262 |
mcopy->m_len = min(ntohs(ip->ip_len), M_TRAILINGSPACE(mcopy)); |
| 263 |
mcopy->m_pkthdr.len = mcopy->m_len; |
| 264 |
m_copydata(m, 0, mcopy->m_len, mtod(mcopy, caddr_t)); |
| 265 |
} |
| 266 |
/* |
| 233 |
* Step 3: incoming packet firewall processing |
267 |
* Step 3: incoming packet firewall processing |
| 234 |
*/ |
268 |
*/ |
| 235 |
|
269 |
|
|
Lines 285-291
Link Here
|
| 285 |
if (!V_ipstealth) { |
319 |
if (!V_ipstealth) { |
| 286 |
#endif |
320 |
#endif |
| 287 |
if (ip->ip_ttl <= IPTTLDEC) { |
321 |
if (ip->ip_ttl <= IPTTLDEC) { |
| 288 |
icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, 0, 0); |
322 |
icmp_error(mcopy, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, 0, 0); |
|
|
323 |
if (mcopy) |
| 324 |
m_freem(mcopy); |
| 289 |
return NULL; /* mbuf already free'd */ |
325 |
return NULL; /* mbuf already free'd */ |
| 290 |
} |
326 |
} |
| 291 |
|
327 |
|
|
Lines 306-313
Link Here
|
| 306 |
/* |
342 |
/* |
| 307 |
* Find route to destination. |
343 |
* Find route to destination. |
| 308 |
*/ |
344 |
*/ |
| 309 |
if ((dst = ip_findroute(&ro, dest, m)) == NULL) |
345 |
if ((dst = ip_findroute(&ro, dest, m)) == NULL) { |
|
|
346 |
if (mcopy) |
| 347 |
m_freem(mcopy); |
| 310 |
return NULL; /* icmp unreach already sent */ |
348 |
return NULL; /* icmp unreach already sent */ |
|
|
349 |
} |
| 311 |
ifp = ro.ro_rt->rt_ifp; |
350 |
ifp = ro.ro_rt->rt_ifp; |
| 312 |
|
351 |
|
| 313 |
/* |
352 |
/* |
|
Lines 355-360
Link Here
|
| 355 |
m->m_flags |= M_FASTFWD_OURS; |
394 |
m->m_flags |= M_FASTFWD_OURS; |
| 356 |
if (ro.ro_rt) |
395 |
if (ro.ro_rt) |
| 357 |
RTFREE(ro.ro_rt); |
396 |
RTFREE(ro.ro_rt); |
|
|
397 |
if (mcopy) |
| 398 |
m_freem(mcopy); |
| 358 |
return m; |
399 |
return m; |
| 359 |
} |
400 |
} |
| 360 |
/* |
401 |
/* |
|
Lines 367-374
Link Here
|
| 367 |
m->m_flags &= ~M_IP_NEXTHOP; |
408 |
m->m_flags &= ~M_IP_NEXTHOP; |
| 368 |
} |
409 |
} |
| 369 |
RTFREE(ro.ro_rt); |
410 |
RTFREE(ro.ro_rt); |
| 370 |
if ((dst = ip_findroute(&ro, dest, m)) == NULL) |
411 |
if ((dst = ip_findroute(&ro, dest, m)) == NULL) { |
|
|
412 |
if (mcopy) |
| 413 |
m_freem(mcopy); |
| 371 |
return NULL; /* icmp unreach already sent */ |
414 |
return NULL; /* icmp unreach already sent */ |
|
|
415 |
} |
| 372 |
ifp = ro.ro_rt->rt_ifp; |
416 |
ifp = ro.ro_rt->rt_ifp; |
| 373 |
} |
417 |
} |
| 374 |
|
418 |
|
|
Lines 384-390
Link Here
|
| 384 |
*/ |
428 |
*/ |
| 385 |
if ((ro.ro_rt->rt_flags & RTF_REJECT) && |
429 |
if ((ro.ro_rt->rt_flags & RTF_REJECT) && |
| 386 |
(ro.ro_rt->rt_expire == 0 || time_uptime < ro.ro_rt->rt_expire)) { |
430 |
(ro.ro_rt->rt_expire == 0 || time_uptime < ro.ro_rt->rt_expire)) { |
| 387 |
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0); |
431 |
icmp_error(mcopy, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0); |
| 388 |
goto consumed; |
432 |
goto consumed; |
| 389 |
} |
433 |
} |
| 390 |
|
434 |
|
|
Lines 392-398
Link Here
|
| 392 |
* Check if media link state of interface is not down |
436 |
* Check if media link state of interface is not down |
| 393 |
*/ |
437 |
*/ |
| 394 |
if (ifp->if_link_state == LINK_STATE_DOWN) { |
438 |
if (ifp->if_link_state == LINK_STATE_DOWN) { |
| 395 |
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0); |
439 |
icmp_error(mcopy, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0); |
| 396 |
goto consumed; |
440 |
goto consumed; |
| 397 |
} |
441 |
} |
| 398 |
|
442 |
|
|
Lines 421-427
Link Here
|
| 421 |
*/ |
465 |
*/ |
| 422 |
if (ip_off & IP_DF) { |
466 |
if (ip_off & IP_DF) { |
| 423 |
IPSTAT_INC(ips_cantfrag); |
467 |
IPSTAT_INC(ips_cantfrag); |
| 424 |
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, |
468 |
icmp_error(mcopy, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, |
| 425 |
0, mtu); |
469 |
0, mtu); |
| 426 |
goto consumed; |
470 |
goto consumed; |
| 427 |
} else { |
471 |
} else { |
|
Lines 469-479
Link Here
|
| 469 |
IPSTAT_INC(ips_fastforward); |
513 |
IPSTAT_INC(ips_fastforward); |
| 470 |
} |
514 |
} |
| 471 |
consumed: |
515 |
consumed: |
|
|
516 |
if (mcopy) |
| 517 |
m_freem(mcopy); |
| 472 |
RTFREE(ro.ro_rt); |
518 |
RTFREE(ro.ro_rt); |
| 473 |
return NULL; |
519 |
return NULL; |
| 474 |
drop: |
520 |
drop: |
| 475 |
if (m) |
521 |
if (m) |
| 476 |
m_freem(m); |
522 |
m_freem(m); |
|
|
523 |
if (mcopy) |
| 524 |
m_freem(mcopy); |
| 477 |
if (ro.ro_rt) |
525 |
if (ro.ro_rt) |
| 478 |
RTFREE(ro.ro_rt); |
526 |
RTFREE(ro.ro_rt); |
| 479 |
return NULL; |
527 |
return NULL; |