* Notify a tcp user of an asynchronous error; * store error as soft error, but wake up user * (for now, won't do anything until can select for soft error). * * Do not wake up user since there currently is no mechanism for * reporting soft errors (yet - a kqueue filter may be added). */
| 2198 | * reporting soft errors (yet - a kqueue filter may be added). |
| 2199 | */ |
| 2200 | static struct inpcb * |
| 2201 | tcp_notify(struct inpcb *inp, int error) |
| 2202 | { |
| 2203 | struct tcpcb *tp; |
| 2204 | |
| 2205 | INP_INFO_LOCK_ASSERT(&V_tcbinfo); |
| 2206 | INP_WLOCK_ASSERT(inp); |
| 2207 | |
| 2208 | if ((inp->inp_flags & INP_TIMEWAIT) || |
| 2209 | (inp->inp_flags & INP_DROPPED)) |
| 2210 | return (inp); |
| 2211 | |
| 2212 | tp = intotcpcb(inp); |
| 2213 | KASSERT(tp != NULL, ("tcp_notify: tp == NULL")); |
| 2214 | |
| 2215 | /* |
| 2216 | * Ignore some errors if we are hooked up. |
| 2217 | * If connection hasn't completed, has retransmitted several times, |
| 2218 | * and receives a second error, give up now. This is better |
| 2219 | * than waiting a long time to establish a connection that |
| 2220 | * can never complete. |
| 2221 | */ |
| 2222 | if (tp->t_state == TCPS_ESTABLISHED && |
| 2223 | (error == EHOSTUNREACH || error == ENETUNREACH || |
| 2224 | error == EHOSTDOWN)) { |
| 2225 | if (inp->inp_route.ro_nh) { |
| 2226 | NH_FREE(inp->inp_route.ro_nh); |
| 2227 | inp->inp_route.ro_nh = (struct nhop_object *)NULL; |
| 2228 | } |
| 2229 | return (inp); |
| 2230 | } else if (tp->t_state < TCPS_ESTABLISHED && tp->t_rxtshift > 3 && |
| 2231 | tp->t_softerror) { |
| 2232 | tp = tcp_drop(tp, error); |
| 2233 | if (tp != NULL) |
| 2234 | return (inp); |
| 2235 | else |
| 2236 | return (NULL); |
| 2237 | } else { |
| 2238 | tp->t_softerror = error; |
| 2239 | return (inp); |
| 2240 | } |
| 2241 | #if 0 |
| 2242 | wakeup( &so->so_timeo); |
| 2243 | sorwakeup(so); |
| 2244 | sowwakeup(so); |
| 2245 | #endif |
| 2246 | } |
| 2247 | |
| 2248 | static int |
| 2249 | tcp_pcblist(SYSCTL_HANDLER_ARGS) |