
![]() |
| // icmp:发送各类ICMP报文 icmp(type, code, dst, pa1, pa2) short type, code; IPaddr dst; char *pa1, *pa2; { struct ep *pep; struct ip *pip; struct icmp *pic; Bool isresp, iserr; IPaddr src; int i, datalen; IcmpOutMsgs++; pep = icsetbuf(type, pa1, &isresp, &iserr); if (pep == 0) { IcmpOutErrors++; return SYSERR; } pip = (struct ip*)pep->ep_data; pic = (struct icmp*)pip->ip_data; datalen = IC_HLEN; /* we fill in the source here, so routing won't break it */ if (isresp) { if (iserr) { if (!icerrok(pep)) { freebuf(pep); return OK; } blkcopy(pic->ic_data, pip, IP_HLEN(pip) + 8); datalen += IP_HLEN(pip) + 8; } icsetsrc(pip); } else pip->ip_src = ip_anyaddr; pip->ip_dst = dst; pic->ic_type = (char)type; pic->ic_code = (char)code; if (!isresp) { if (type == ICT_ECHORQ) pic->ic_seq = (int)pa1; else pic->ic_seq = 0; pic->ic_id = getpid(); } datalen += icsetdata(type, pip, pa2); pic->ic_cksum = 0; pic->ic_cksum = cksum(pic, datalen); ipsend(dst, pep, datalen, IPT_ICMP, IPP_INCTL, IP_TTL); return OK; } // icsetdata:根据报文类型填充相应的数据 int icsetdata(type, pip, pa2) int type; struct ip *pip; char *pa2; { struct icmp *pic = (struct icmp *)pip->ip_data; int i, len; switch (type) { case ICT_ECHORP: len = pip->ip_len - IP_HLEN(pip) - IC_HLEN; if (isodd(len)) pic->ic_data[len] = 0; /* so cksum works */ return len; case ICT_DESTUR: case ICT_SRCQ: case ICT_TIMEX: pic->ic_mbz = 0; /* must be 0 */ break; case ICT_REDIRECT: pic->ic_gw = (IPaddr)pa2; break; case ICT_PARAMP: pic->ic_ptr = (char) pa2; for (i=0; i<IC_PADLEN; ++i) pic->ic_pad[i] = 0; break; case ICT_MASKRP: blkcopy(pic->ic_data, &pa2, IP_ALEN); break; case ICT_ECHORQ: if ((int)pa2 > ECHOMAX(pip)) pa2 = (char *)ECHOMAX(pip); for (i=0; i<(int)pa2; ++i) pic->ic_data[i] = i; return (int)pa2; case ICT_MASKRQ: blkcopy(pic->ic_data, &ip_anyaddr, IP_ALEN); return IP_ALEN; } return 0; } |
| // icredirect:处理接收到的ICMP redirect报文,刷新路由缓存 int icredirect(pep) struct ep *pep; { struct route *prt; struct ip *pip, *pip2; struct icmp *pic; IPaddr mask; pip = (struct ip*)pep->ep_data; pic = (struct icmp*)pip->ip_data; pip2 = (struct ip*)pic->ic_data; if (pic->ic_code == ICC_HOSTRD) mask = ip_maskall; else netmask(mask, pip2->ip_dst); prt = rtget(pip2->ip_dst, RTF_LOCAL); if (prt == 0) { freebuf(pep); return OK; } if (pip->ip_src == prt->rt_gw) { rtdel(pip2->ip_dst, mask); rtadd(pip2->ip_dst, mask, pic->ic_gw, prt->rt_metric, prt->rt_ifnum,IC_RDTTL); } rtfree(prt); freebuf(pep); return OK; } |