demux.c
来自「ipsec vpn」· C语言 代码 · 共 2,148 行 · 第 1/5 页
C
2,148 行
break; case SO_EE_ORIGIN_ICMP6: snprintf(orname, sizeof(orname) , "ICMP6 type %d code %d (not authenticated)" , ee->ee_type, ee->ee_code ); break; default: snprintf(orname, sizeof(orname), "invalid origin %lu" , (unsigned long) ee->ee_origin); break; } { struct state *old_state = cur_state; cur_state = sender; /* note dirty trick to suppress ~ at start of format * if we know what state to blame. */#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 (sport=%d)" "%s" ", complainant %s" ": %s" " [errno %lu, origin %s" /* ", pad %d, info %ld" */ /* ", data %ld" */ "]" , ifp->ip_dev->id_rname , ifp->port , 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 if (cm->cmsg_level == SOL_IP && cm->cmsg_type == IP_PKTINFO) { } 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) */boolsend_packet(struct state *st, const char *where, bool verbose){ bool err; u_int8_t ike_pkt[MAX_OUTPUT_UDP_SIZE]; u_int8_t *ptr; unsigned long len; ssize_t wlen; if ((st->st_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; } DBG(DBG_CONTROL|DBG_RAW , DBG_log("sending %lu bytes for %s through %s:%d to %s:%u:" , (unsigned long) st->st_tpacket.len , where , st->st_interface->ip_dev->id_rname , st->st_interface->port , ip_str(&st->st_remoteaddr) , st->st_remoteport)); DBG(DBG_RAW , DBG_dump(NULL, ptr, len)); setportof(htons(st->st_remoteport), &st->st_remoteaddr);#if defined(IP_RECVERR) && defined(MSG_ERRQUEUE) (void) check_msg_errqueue(st->st_interface, POLLOUT);#endif /* defined(IP_RECVERR) && defined(MSG_ERRQUEUE) */#if 0 wlen = sendfromto(st->st_interface->fd , ptr , len, 0 , sockaddrof(&st->st_remoteaddr) , sockaddrlenof(&st->st_remoteaddr) , sockaddrof(&st->st_localaddr) , sockaddrlenof(&st->st_localaddr));#else wlen = sendto(st->st_interface->fd , ptr , len, 0 , sockaddrof(&st->st_remoteaddr) , sockaddrlenof(&st->st_remoteaddr));#ifdef DEBUG if(DBGP(IMPAIR_JACOB_TWO_TWO)) { /* sleep for half a second, and second another packet */ usleep(500000); DBG_log("JACOB 2-2: resending %lu bytes for %s through %s:%d to %s:%u:" , (unsigned long) st->st_tpacket.len , where , st->st_interface->ip_dev->id_rname , st->st_interface->port , ip_str(&st->st_remoteaddr) , st->st_remoteport);#endif wlen = sendto(st->st_interface->fd , ptr , len, 0 , sockaddrof(&st->st_remoteaddr) , sockaddrlenof(&st->st_remoteaddr)); } #endif err = (wlen != (ssize_t)len); if (err) { /* do not log NAT-T Keep Alive packets */ if (!verbose) return FALSE; log_errno((e, "sendto on %s to %s:%u failed in %s" , st->st_interface->ip_dev->id_rname , ip_str(&st->st_remoteaddr) , st->st_remoteport , 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. */ DBG(DBG_CONTROL, DBG_log("processing informational %s (%d)" , enum_name(&ipsec_notification_names ,n->isan_type) , n->isan_type)); 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:#ifdef DEBUG if(st!=NULL && st->st_connection->extra_debugging & IMPAIR_DIE_ONINFO) { loglog(RC_LOG_SERIOUS, "received and failed on unknown informational message"); return STF_FATAL; }#endif 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; passert(md_pool != md->next); 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); /* make sure we are not creating a loop */ passert(md != md_pool); 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_port *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_port *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,to; int from_len = sizeof(from); int to_len = sizeof(to); err_t from_ugh = NULL; static const char undisclosed[] = "unknown source"; happy(anyaddr(addrtypeof(&ifp->ip_addr), &md->sender)); zero(&from.sa); packet_len = recvfromto(ifp->fd, bigbuffer , sizeof(bigbuffer), /*flags*/0 , &from.sa, &from_len , &to.sa, &to_len); /* we do not do anything with *to* addresses yet... we will */ /* 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"; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?