| 242 | } |
| 243 | |
| 244 | void |
| 245 | sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip) |
| 246 | { |
| 247 | struct ip *outer_ip; |
| 248 | struct ip *inner_ip; |
| 249 | struct sctphdr *sh; |
| 250 | struct icmp *icmp; |
| 251 | struct sctp_inpcb *inp; |
| 252 | struct sctp_tcb *stcb; |
| 253 | struct sctp_nets *net; |
| 254 | struct sctp_init_chunk *ch; |
| 255 | struct sockaddr_in src, dst; |
| 256 | |
| 257 | if (sa->sa_family != AF_INET || |
| 258 | ((struct sockaddr_in *)sa)->sin_addr.s_addr == INADDR_ANY) { |
| 259 | return; |
| 260 | } |
| 261 | if (PRC_IS_REDIRECT(cmd)) { |
| 262 | vip = NULL; |
| 263 | } else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) { |
| 264 | return; |
| 265 | } |
| 266 | if (vip != NULL) { |
| 267 | inner_ip = (struct ip *)vip; |
| 268 | icmp = (struct icmp *)((caddr_t)inner_ip - |
| 269 | (sizeof(struct icmp) - sizeof(struct ip))); |
| 270 | outer_ip = (struct ip *)((caddr_t)icmp - sizeof(struct ip)); |
| 271 | sh = (struct sctphdr *)((caddr_t)inner_ip + (inner_ip->ip_hl << 2)); |
| 272 | memset(&src, 0, sizeof(struct sockaddr_in)); |
| 273 | src.sin_family = AF_INET; |
| 274 | src.sin_len = sizeof(struct sockaddr_in); |
| 275 | src.sin_port = sh->src_port; |
| 276 | src.sin_addr = inner_ip->ip_src; |
| 277 | memset(&dst, 0, sizeof(struct sockaddr_in)); |
| 278 | dst.sin_family = AF_INET; |
| 279 | dst.sin_len = sizeof(struct sockaddr_in); |
| 280 | dst.sin_port = sh->dest_port; |
| 281 | dst.sin_addr = inner_ip->ip_dst; |
| 282 | /* |
| 283 | * 'dst' holds the dest of the packet that failed to be |
| 284 | * sent. 'src' holds our local endpoint address. Thus we |
| 285 | * reverse the dst and the src in the lookup. |
| 286 | */ |
| 287 | inp = NULL; |
| 288 | net = NULL; |
| 289 | stcb = sctp_findassociation_addr_sa((struct sockaddr *)&dst, |
| 290 | (struct sockaddr *)&src, |
| 291 | &inp, &net, 1, |
| 292 | SCTP_DEFAULT_VRFID); |
| 293 | if ((stcb != NULL) && |
| 294 | (net != NULL) && |
| 295 | (inp != NULL)) { |
| 296 | /* Check the verification tag */ |
| 297 | if (ntohl(sh->v_tag) != 0) { |
| 298 | /* |
| 299 | * This must be the verification tag used |
| 300 | * for sending out packets. We don't |
| 301 | * consider packets reflecting the |
nothing calls this directly
no test coverage detected