| version 1.74.2.1, 1998/12/11 04:53:08 |
version 1.75, 1998/12/18 21:35:11 |
| Line 164 struct ifqueue ipintrq; |
|
| Line 164 struct ifqueue ipintrq; |
|
| struct ipstat ipstat; |
struct ipstat ipstat; |
| u_int16_t ip_id; |
u_int16_t ip_id; |
| int ip_defttl; |
int ip_defttl; |
| |
|
| struct ipqhead ipq; |
struct ipqhead ipq; |
| |
int ipq_locked; |
| |
|
| |
static __inline int ipq_lock_try __P((void)); |
| |
static __inline void ipq_unlock __P((void)); |
| |
|
| |
static __inline int |
| |
ipq_lock_try() |
| |
{ |
| |
int s; |
| |
|
| |
s = splimp(); |
| |
if (ipq_locked) { |
| |
splx(s); |
| |
return (0); |
| |
} |
| |
ipq_locked = 1; |
| |
splx(s); |
| |
return (1); |
| |
} |
| |
|
| |
static __inline void |
| |
ipq_unlock() |
| |
{ |
| |
int s; |
| |
|
| |
s = splimp(); |
| |
ipq_locked = 0; |
| |
splx(s); |
| |
} |
| |
|
| |
#ifdef DIAGNOSTIC |
| |
#define IPQ_LOCK() \ |
| |
do { \ |
| |
if (ipq_lock_try() == 0) { \ |
| |
printf("%s:%d: ipq already locked\n", __FILE__, __LINE__); \ |
| |
panic("ipq_lock"); \ |
| |
} \ |
| |
} while (0) |
| |
#define IPQ_LOCK_CHECK() \ |
| |
do { \ |
| |
if (ipq_locked == 0) { \ |
| |
printf("%s:%d: ipq lock not held\n", __FILE__, __LINE__); \ |
| |
panic("ipq lock check"); \ |
| |
} \ |
| |
} while (0) |
| |
#else |
| |
#define IPQ_LOCK() (void) ipq_lock_try() |
| |
#define IPQ_LOCK_CHECK() /* nothing */ |
| |
#endif |
| |
|
| |
#define IPQ_UNLOCK() ipq_unlock() |
| |
|
| struct pool ipqent_pool; |
struct pool ipqent_pool; |
| |
|
|
|
| /* |
/* |
| * Check our list of addresses, to see if the packet is for us. |
* Check our list of addresses, to see if the packet is for us. |
| */ |
*/ |
| s = splimp(); |
|
| INADDR_TO_IA(ip->ip_dst, ia); |
INADDR_TO_IA(ip->ip_dst, ia); |
| if (ia != NULL) { |
if (ia != NULL) goto ours; |
| ifa_delref(&ia->ia_ifa); |
|
| splx(s); |
|
| goto ours; |
|
| } |
|
| if (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) { |
if (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) { |
| for (ifa = m->m_pkthdr.rcvif->if_addrlist.tqh_first; |
for (ifa = m->m_pkthdr.rcvif->if_addrlist.tqh_first; |
| ifa != NULL; ifa = ifa->ifa_list.tqe_next) { |
ifa != NULL; ifa = ifa->ifa_list.tqe_next) { |
| if (ifa->ifa_addr->sa_family != AF_INET) continue; |
if (ifa->ifa_addr->sa_family != AF_INET) continue; |
| ia = ifatoia(ifa); |
ia = ifatoia(ifa); |
| /* |
|
| * Don't ifa_addref ia as we don't use it after |
|
| * we splx(s) below |
|
| */ |
|
| if (in_hosteq(ip->ip_dst, ia->ia_broadaddr.sin_addr) || |
if (in_hosteq(ip->ip_dst, ia->ia_broadaddr.sin_addr) || |
| in_hosteq(ip->ip_dst, ia->ia_netbroadcast) || |
in_hosteq(ip->ip_dst, ia->ia_netbroadcast) || |
| /* |
/* |
|
|
| * either for subnet or net. |
* either for subnet or net. |
| */ |
*/ |
| ip->ip_dst.s_addr == ia->ia_subnet || |
ip->ip_dst.s_addr == ia->ia_subnet || |
| ip->ip_dst.s_addr == ia->ia_net) { |
ip->ip_dst.s_addr == ia->ia_net) |
| splx(s); |
|
| goto ours; |
goto ours; |
| } |
|
| /* |
/* |
| * An interface with IP address zero accepts |
* An interface with IP address zero accepts |
| * all packets that arrive on that interface. |
* all packets that arrive on that interface. |
| */ |
*/ |
| if (in_nullhost(ia->ia_addr.sin_addr)) { |
if (in_nullhost(ia->ia_addr.sin_addr)) |
| splx(s); |
|
| goto ours; |
goto ours; |
| } |
|
| } |
} |
| } |
} |
| splx(s); |
|
| if (IN_MULTICAST(ip->ip_dst.s_addr)) { |
if (IN_MULTICAST(ip->ip_dst.s_addr)) { |
| struct in_multi *inm; |
struct in_multi *inm; |
| #ifdef MROUTING |
#ifdef MROUTING |
|
|
| * Look for queue of fragments |
* Look for queue of fragments |
| * of this datagram. |
* of this datagram. |
| */ |
*/ |
| |
IPQ_LOCK(); |
| for (fp = ipq.lh_first; fp != NULL; fp = fp->ipq_q.le_next) |
for (fp = ipq.lh_first; fp != NULL; fp = fp->ipq_q.le_next) |
| if (ip->ip_id == fp->ipq_id && |
if (ip->ip_id == fp->ipq_id && |
| in_hosteq(ip->ip_src, fp->ipq_src) && |
in_hosteq(ip->ip_src, fp->ipq_src) && |
|
|
| */ |
*/ |
| if (ip->ip_len == 0 || (ip->ip_len & 0x7) != 0) { |
if (ip->ip_len == 0 || (ip->ip_len & 0x7) != 0) { |
| ipstat.ips_badfrags++; |
ipstat.ips_badfrags++; |
| |
IPQ_UNLOCK(); |
| goto bad; |
goto bad; |
| } |
} |
| } |
} |
|
|
| ipqe = pool_get(&ipqent_pool, PR_NOWAIT); |
ipqe = pool_get(&ipqent_pool, PR_NOWAIT); |
| if (ipqe == NULL) { |
if (ipqe == NULL) { |
| ipstat.ips_rcvmemdrop++; |
ipstat.ips_rcvmemdrop++; |
| |
IPQ_UNLOCK(); |
| goto bad; |
goto bad; |
| } |
} |
| ipqe->ipqe_mff = mff; |
ipqe->ipqe_mff = mff; |
| ipqe->ipqe_m = m; |
ipqe->ipqe_m = m; |
| ipqe->ipqe_ip = ip; |
ipqe->ipqe_ip = ip; |
| m = ip_reass(ipqe, fp); |
m = ip_reass(ipqe, fp); |
| if (m == 0) |
if (m == 0) { |
| |
IPQ_UNLOCK(); |
| goto next; |
goto next; |
| |
} |
| ipstat.ips_reassembled++; |
ipstat.ips_reassembled++; |
| ip = mtod(m, struct ip *); |
ip = mtod(m, struct ip *); |
| hlen = ip->ip_hl << 2; |
hlen = ip->ip_hl << 2; |
| } else |
} else |
| if (fp) |
if (fp) |
| ip_freef(fp); |
ip_freef(fp); |
| |
IPQ_UNLOCK(); |
| } else |
} else |
| ip->ip_len -= hlen; |
ip->ip_len -= hlen; |
| |
|
| Line 564 ip_reass(ipqe, fp) |
|
| Line 608 ip_reass(ipqe, fp) |
|
| int hlen = ipqe->ipqe_ip->ip_hl << 2; |
int hlen = ipqe->ipqe_ip->ip_hl << 2; |
| int i, next; |
int i, next; |
| |
|
| |
IPQ_LOCK_CHECK(); |
| |
|
| /* |
/* |
| * Presence of header sizes in mbufs |
* Presence of header sizes in mbufs |
| * would confuse code below. |
* would confuse code below. |
|
|
| { |
{ |
| register struct ipqent *q, *p; |
register struct ipqent *q, *p; |
| |
|
| |
IPQ_LOCK_CHECK(); |
| |
|
| for (q = fp->ipq_fragq.lh_first; q != NULL; q = p) { |
for (q = fp->ipq_fragq.lh_first; q != NULL; q = p) { |
| p = q->ipqe_q.le_next; |
p = q->ipqe_q.le_next; |
| m_freem(q->ipqe_m); |
m_freem(q->ipqe_m); |
|
|
| register struct ipq *fp, *nfp; |
register struct ipq *fp, *nfp; |
| int s = splsoftnet(); |
int s = splsoftnet(); |
| |
|
| |
IPQ_LOCK(); |
| for (fp = ipq.lh_first; fp != NULL; fp = nfp) { |
for (fp = ipq.lh_first; fp != NULL; fp = nfp) { |
| nfp = fp->ipq_q.le_next; |
nfp = fp->ipq_q.le_next; |
| if (--fp->ipq_ttl == 0) { |
if (--fp->ipq_ttl == 0) { |
|
|
| ip_freef(fp); |
ip_freef(fp); |
| } |
} |
| } |
} |
| |
IPQ_UNLOCK(); |
| #ifdef GATEWAY |
#ifdef GATEWAY |
| ipflow_slowtimo(); |
ipflow_slowtimo(); |
| #endif |
#endif |
|
|
| ip_drain() |
ip_drain() |
| { |
{ |
| |
|
| |
/* |
| |
* We may be called from a device's interrupt context. If |
| |
* the ipq is already busy, just bail out now. |
| |
*/ |
| |
if (ipq_lock_try() == 0) |
| |
return; |
| |
|
| while (ipq.lh_first != NULL) { |
while (ipq.lh_first != NULL) { |
| ipstat.ips_fragdropped++; |
ipstat.ips_fragdropped++; |
| ip_freef(ipq.lh_first); |
ip_freef(ipq.lh_first); |
| } |
} |
| |
|
| |
IPQ_UNLOCK(); |
| } |
} |
| |
|
| /* |
/* |
|
|
| * End of source route. Should be for us. |
* End of source route. Should be for us. |
| */ |
*/ |
| save_rte(cp, ip->ip_src); |
save_rte(cp, ip->ip_src); |
| ifa_delref(&ia->ia_ifa); |
|
| break; |
break; |
| } |
} |
| /* |
/* |
|
|
| */ |
*/ |
| bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr, |
bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr, |
| sizeof(ipaddr.sin_addr)); |
sizeof(ipaddr.sin_addr)); |
| ifa_delref(&ia->ia_ifa); |
|
| if (opt == IPOPT_SSRR) { |
if (opt == IPOPT_SSRR) { |
| #define INA struct in_ifaddr * |
#define INA struct in_ifaddr * |
| #define SA struct sockaddr * |
#define SA struct sockaddr * |
|
|
| * Let ip_intr's mcast routing check handle mcast pkts |
* Let ip_intr's mcast routing check handle mcast pkts |
| */ |
*/ |
| forward = !IN_MULTICAST(ip->ip_dst.s_addr); |
forward = !IN_MULTICAST(ip->ip_dst.s_addr); |
| ifa_delref(&ia->ia_ifa); |
|
| break; |
break; |
| |
|
| case IPOPT_RR: |
case IPOPT_RR: |
|
|
| bcopy((caddr_t)&ia->ia_addr.sin_addr, |
bcopy((caddr_t)&ia->ia_addr.sin_addr, |
| (caddr_t)(cp + off), sizeof(struct in_addr)); |
(caddr_t)(cp + off), sizeof(struct in_addr)); |
| cp[IPOPT_OFFSET] += sizeof(struct in_addr); |
cp[IPOPT_OFFSET] += sizeof(struct in_addr); |
| ifa_delref(&ia->ia_ifa); |
|
| break; |
break; |
| |
|
| case IPOPT_TS: |
case IPOPT_TS: |
|
|
| continue; |
continue; |
| bcopy((caddr_t)&ia->ia_addr.sin_addr, |
bcopy((caddr_t)&ia->ia_addr.sin_addr, |
| (caddr_t)sin, sizeof(struct in_addr)); |
(caddr_t)sin, sizeof(struct in_addr)); |
| ifa_delref(&ia->ia_ifa); |
|
| ipt->ipt_ptr += sizeof(struct in_addr); |
ipt->ipt_ptr += sizeof(struct in_addr); |
| break; |
break; |
| |
|
|
|
| goto bad; |
goto bad; |
| bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr, |
bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr, |
| sizeof(struct in_addr)); |
sizeof(struct in_addr)); |
| ia = (INA)ifa_ifwithaddr((SA)&ipaddr); |
if (ifa_ifwithaddr((SA)&ipaddr) == 0) |
| if (ia == 0) |
|
| continue; |
continue; |
| ifa_delref(&ia->ia_ifa); |
|
| ipt->ipt_ptr += sizeof(struct in_addr); |
ipt->ipt_ptr += sizeof(struct in_addr); |
| break; |
break; |
| |
|
|
|
| struct in_addr dst; |
struct in_addr dst; |
| { |
{ |
| register struct sockaddr_in *sin; |
register struct sockaddr_in *sin; |
| struct in_ifaddr *ia; |
|
| int s; |
|
| |
|
| sin = satosin(&ipforward_rt.ro_dst); |
sin = satosin(&ipforward_rt.ro_dst); |
| |
|
|
|
| } |
} |
| if (ipforward_rt.ro_rt == 0) |
if (ipforward_rt.ro_rt == 0) |
| return ((struct in_ifaddr *)0); |
return ((struct in_ifaddr *)0); |
| s = splimp(); |
return (ifatoia(ipforward_rt.ro_rt->rt_ifa)); |
| ia = (ifatoia(ipforward_rt.ro_rt->rt_ifa)); |
|
| ifa_addref(&ia->ia_ifa); |
|
| splx(s); |
|
| return ia; |
|
| } |
} |
| |
|
| /* |
/* |