📄 demux.c
字号:
*/#ifdef NAT_TRAVERSAL if ((packet_len == 1) && (buffer[0] = 0xff)#ifdef DEBUG && ((cur_debugging & DBG_NATT) == 0)#endif ) { /* don't log NAT-T keepalive related errors unless NATT debug is * enabled */ } else#endif openswan_log((sender != NULL) + "~" "ERROR: asynchronous network error report on %s" "%s" ", complainant %s" ": %s" " [errno %lu, origin %s" /* ", pad %d, info %ld" */ /* ", data %ld" */ "]" , ifp->rname , fromstr , offstr , strerror(ee->ee_errno) , (unsigned long) ee->ee_errno , orname /* , ee->ee_pad, (unsigned long)ee->ee_info */ /* , (unsigned long)ee->ee_data */ ); cur_state = old_state; } } else { /* .cmsg_len is a kernel_size_t(!), but the value * certainly ought to fit in an unsigned long. */ openswan_log("unknown cmsg: level %d, type %d, len %lu" , cm->cmsg_level, cm->cmsg_type , (unsigned long) cm->cmsg_len); } } } return (pfd.revents & interest) != 0;}#endif /* defined(IP_RECVERR) && defined(MSG_ERRQUEUE) */bool#ifdef NAT_TRAVERSAL_send_packet(struct state *st, const char *where, bool verbose)#elsesend_packet(struct state *st, const char *where)#endif{ struct connection *c = st->st_connection; int port_buf; bool err;#ifdef NAT_TRAVERSAL u_int8_t ike_pkt[MAX_OUTPUT_UDP_SIZE]; u_int8_t *ptr; unsigned long len; if ((c->interface->ike_float == TRUE) && (st->st_tpacket.len != 1)) { if ((unsigned long) st->st_tpacket.len > (MAX_OUTPUT_UDP_SIZE-sizeof(u_int32_t))) { DBG_log("send_packet(): really too big"); return FALSE; } ptr = ike_pkt; /** Add Non-ESP marker **/ memset(ike_pkt, 0, sizeof(u_int32_t)); memcpy(ike_pkt + sizeof(u_int32_t), st->st_tpacket.ptr, (unsigned long)st->st_tpacket.len); len = (unsigned long) st->st_tpacket.len + sizeof(u_int32_t); } else { ptr = st->st_tpacket.ptr; len = (unsigned long) st->st_tpacket.len; }#endif DBG(DBG_RAW, { DBG_log("sending %lu bytes for %s through %s to %s:%u:" , (unsigned long) st->st_tpacket.len , where , c->interface->rname , ip_str(&c->spd.that.host_addr) , (unsigned)c->spd.that.host_port); DBG_dump_chunk(NULL, st->st_tpacket); }); /* XXX: Not very clean. We manipulate the port of the ip_address to * have a port in the sockaddr*, but we retain the original port * and restore it afterwards. */ port_buf = portof(&c->spd.that.host_addr); setportof(htons(c->spd.that.host_port), &c->spd.that.host_addr);#if defined(IP_RECVERR) && defined(MSG_ERRQUEUE) (void) check_msg_errqueue(c->interface, POLLOUT);#endif /* defined(IP_RECVERR) && defined(MSG_ERRQUEUE) */#ifdef NAT_TRAVERSAL err = sendto(c->interface->fd , ptr, len, 0 , sockaddrof(&c->spd.that.host_addr) , sockaddrlenof(&c->spd.that.host_addr)) != (ssize_t)len;#else err = sendto(c->interface->fd , st->st_tpacket.ptr, st->st_tpacket.len, 0 , sockaddrof(&c->spd.that.host_addr) , sockaddrlenof(&c->spd.that.host_addr)) != (ssize_t)st->st_tpacket.len;#endif /* restore port */ setportof(port_buf, &c->spd.that.host_addr); if (err) {#ifdef NAT_TRAVERSAL /* do not log NAT-T Keep Alive packets */ if (!verbose) return FALSE; #endif log_errno((e, "sendto on %s to %s:%u failed in %s" , c->interface->rname , ip_str(&c->spd.that.host_addr) , (unsigned)c->spd.that.host_port , where)); return FALSE; } else { return TRUE; }}static stf_statusunexpected(struct msg_digest *md){ loglog(RC_LOG_SERIOUS, "unexpected message received in state %s" , enum_name(&state_names, md->st->st_state)); return STF_IGNORE;}static stf_statusinformational(struct msg_digest *md){ struct payload_digest *const n_pld = md->chain[ISAKMP_NEXT_N]; /* If the Notification Payload is not null... */ if (n_pld != NULL) { pb_stream *const n_pbs = &n_pld->pbs; struct isakmp_notification *const n = &n_pld->payload.notification; int disp_len; char disp_buf[200]; struct state *st = md->st; /* may be NULL */ /* Switch on Notification Type (enum) */ /* note that we can get notification payloads unencrypted * once we are at least in R3/I4. * and that the handler is expected to treat them suspiciously. */ switch (n->isan_type) { case R_U_THERE: return dpd_inI_outR(st, n, n_pbs); case R_U_THERE_ACK: return dpd_inR(st, n, n_pbs); case PAYLOAD_MALFORMED: if(st) { st->hidden_variables.st_malformed_received++; openswan_log("received %u malformed payload notifies" , st->hidden_variables.st_malformed_received); if(st->hidden_variables.st_malformed_sent > MAXIMUM_MALFORMED_NOTIFY/2 && ((st->hidden_variables.st_malformed_sent + st->hidden_variables.st_malformed_received) > MAXIMUM_MALFORMED_NOTIFY)) { openswan_log("too many malformed payloads (we sent %u and received %u" , st->hidden_variables.st_malformed_sent , st->hidden_variables.st_malformed_received); delete_state(st); } } return STF_IGNORE; default: if (pbs_left(n_pbs) >= sizeof(disp_buf)-1) disp_len = sizeof(disp_buf)-1; else disp_len = pbs_left(n_pbs); memcpy(disp_buf, n_pbs->cur, disp_len); disp_buf[disp_len] = '\0'; break; } } loglog(RC_LOG_SERIOUS, "received and ignored informational message"); return STF_IGNORE;}/* message digest allocation and deallocation */static struct msg_digest *md_pool = NULL;/* free_md_pool is only used to avoid leak reports */voidfree_md_pool(void){ for (;;) { struct msg_digest *md = md_pool; if (md == NULL) break; md_pool = md->next; pfree(md); }}struct msg_digest *alloc_md(void){ struct msg_digest *md = md_pool; /* convenient initializer: * - all pointers NULL * - .note = NOTHING_WRONG * - .encrypted = FALSE */ static const struct msg_digest blank_md; if (md == NULL) md = alloc_thing(struct msg_digest, "msg_digest"); else md_pool = md->next; *md = blank_md; md->digest_roof = md->digest; /* note: although there may be multiple msg_digests at once * (due to suspended state transitions), there is a single * global reply_buffer. It will need to be saved and restored. */ init_pbs(&md->reply, reply_buffer, sizeof(reply_buffer), "reply packet"); return md;}struct state *looking_for_state = NULL;struct msg_digest *looking_for_md = NULL;voidrelease_md(struct msg_digest *md){ passert(looking_for_md == NULL || md != looking_for_md); passert(looking_for_state == NULL || md->st != looking_for_state); freeanychunk(md->raw_packet); pfreeany(md->packet_pbs.start); md->packet_pbs.start = NULL; md->next = md_pool; md_pool = md;}/* wrapper for read_packet and process_packet * * The main purpose of this wrapper is to factor out teardown code * from the many return points in process_packet. This amounts to * releasing the msg_digest and resetting global variables. * * When processing of a packet is suspended (STF_SUSPEND), * process_packet sets md to NULL to prevent the msg_digest being freed. * Someone else must ensure that msg_digest is freed eventually. * * read_packet is broken out to minimize the lifetime of the * enormous input packet buffer, an auto. */voidcomm_handle(const struct iface *ifp){ static struct msg_digest *md;#if defined(IP_RECVERR) && defined(MSG_ERRQUEUE) /* Even though select(2) says that there is a message, * it might only be a MSG_ERRQUEUE message. At least * sometimes that leads to a hanging recvfrom. To avoid * what appears to be a kernel bug, check_msg_errqueue * uses poll(2) and tells us if there is anything for us * to read. * * This is early enough that teardown isn't required: * just return on failure. */ if (!check_msg_errqueue(ifp, POLLIN)) return; /* no normal message to read */#endif /* defined(IP_RECVERR) && defined(MSG_ERRQUEUE) */ md = alloc_md(); md->iface = ifp; if (read_packet(md)) process_packet(&md); if (md != NULL) release_md(md); cur_state = NULL; reset_cur_connection(); cur_from = NULL;}/* read the message. * Since we don't know its size, we read it into * an overly large buffer and then copy it to a * new, properly sized buffer. */static boolread_packet(struct msg_digest *md){ const struct iface *ifp = md->iface; int packet_len; /* ??? this buffer seems *way* too big */ u_int8_t bigbuffer[MAX_INPUT_UDP_SIZE];#ifdef NAT_TRAVERSAL u_int8_t *_buffer = bigbuffer;#endif union { struct sockaddr sa; struct sockaddr_in sa_in4; struct sockaddr_in6 sa_in6; } from; int from_len = sizeof(from); err_t from_ugh = NULL; static const char undisclosed[] = "unknown source"; happy(anyaddr(addrtypeof(&ifp->addr), &md->sender)); zero(&from.sa); packet_len = recvfrom(ifp->fd, bigbuffer, sizeof(bigbuffer), 0 , &from.sa, &from_len); /* First: digest the from address. * We presume that nothing here disturbs errno. */ if (packet_len == -1 && from_len == sizeof(from) && all_zero((const void *)&from.sa, sizeof(from))) { /* "from" is untouched -- not set by recvfrom */ from_ugh = undisclosed; } else if (from_len < (int) (offsetof(struct sockaddr, sa_family) + sizeof(from.sa.sa_family))) { from_ugh = "truncated"; } else { const struct af_info *afi = aftoinfo(from.sa.sa_family); if (afi == NULL) { from_ugh = "unexpected Address Family"; } else if (from_len != (int)afi->sa_sz) { from_ugh = "wrong length"; } else { switch (from.sa.sa_family) { case AF_INET: from_ugh = initaddr((void *) &from.sa_in4.sin_addr , sizeof(from.sa_in4.sin_addr), AF_INET, &md->sender); md->sender_port = ntohs(from.sa_in4.sin_port); break; case AF_INET6: from_ugh = initaddr((void *) &from.sa_in6.sin6_addr , sizeof(from.sa_in6.sin6_addr), AF_INET6, &md->sender); md->sender_port = ntohs(from.sa_in6.sin6_port); break; } } } /* now we report any actual I/O error */ if (packet_len == -1) { if (from_ugh == undisclosed && errno == ECONNREFUSED) { /* Tone down scary message for vague event: * We get "connection refused" in response to some * datagram we sent, but we cannot tell which one. */ openswan_log("some IKE message we sent has been rejected with ECONNREFUSED (kernel supplied no details)"); } else if (from_ugh != NULL) { log_errno((e, "recvfrom on %s failed; Pluto cannot decode source sockaddr in rejection: %s" , ifp->rname, from_ugh)); } else { log_errno((e, "recvfrom on %s from %s:%u failed" , ifp->rname , ip_str(&md->sender), (unsigned)md->sender_port)); } return FALSE; } else if (from_ugh != NULL) { openswan_log("recvfrom on %s returned misformed source sockaddr: %s" , ifp->rname, from_ugh); return FALSE; } cur_from = &md->sender;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -