📄 demux.c
字号:
EVENT_SA_REPLACE, aggr_inR1_outI2 }, /* STATE_AGGR_R1: * SMF_PSK_AUTH: HDR*, HASH_I --> done * SMF_DS_AUTH: HDR*, SIG_I --> done */ { STATE_AGGR_R1, STATE_AGGR_R2, SMF_PSK_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2, P(HASH), P(VID) | P(NATD_RFC), PT(NONE), EVENT_SA_REPLACE, aggr_inI2 }, /* STATE_AGGR_R1: HDR*, HASH_I --> done */ { STATE_AGGR_R1, STATE_AGGR_R2, SMF_DS_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2, P(SIG), P(VID) | P(NATD_RFC), PT(NONE), EVENT_SA_REPLACE, aggr_inI2 }, /* STATE_AGGR_I2: can only get here due to packet loss */ { STATE_AGGR_I2, STATE_UNDEFINED, SMF_ALL_AUTH | SMF_INITIATOR | SMF_RETRANSMIT_ON_DUPLICATE, LEMPTY, LEMPTY, PT(NONE), EVENT_NULL, unexpected }, /* STATE_AGGR_R2: can only get here due to packet loss */ { STATE_AGGR_R2, STATE_UNDEFINED, SMF_ALL_AUTH, LEMPTY, LEMPTY, PT(NONE), EVENT_NULL, unexpected }, /***** Phase 2 Quick Mode *****/ /* No state for quick_outI1: * --> HDR*, HASH(1), SA, Nr [, KE ] [, IDci, IDcr ] */ /* STATE_QUICK_R0: * HDR*, HASH(1), SA, Ni [, KE ] [, IDci, IDcr ] --> * HDR*, HASH(2), SA, Nr [, KE ] [, IDci, IDcr ] * Installs inbound IPsec SAs. * Because it may suspend for asynchronous DNS, first_out_payload * is set to NONE to suppress early emission of HDR*. * ??? it is legal to have multiple SAs, but we don't support it yet. */ { STATE_QUICK_R0, STATE_QUICK_R1 , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY#ifdef NAT_TRAVERSAL , P(HASH) | P(SA) | P(NONCE), /* P(SA) | */ P(KE) | P(ID) | P(NATOA_RFC), PT(NONE)#else , P(HASH) | P(SA) | P(NONCE), /* P(SA) | */ P(KE) | P(ID), PT(NONE)#endif , EVENT_RETRANSMIT, quick_inI1_outR1 }, /* STATE_QUICK_I1: * HDR*, HASH(2), SA, Nr [, KE ] [, IDci, IDcr ] --> * HDR*, HASH(3) * Installs inbound and outbound IPsec SAs, routing, etc. * ??? it is legal to have multiple SAs, but we don't support it yet. */ { STATE_QUICK_I1, STATE_QUICK_I2 , SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED | SMF_REPLY#ifdef NAT_TRAVERSAL , P(HASH) | P(SA) | P(NONCE), /* P(SA) | */ P(KE) | P(ID) | P(NATOA_RFC), PT(HASH)#else , P(HASH) | P(SA) | P(NONCE), /* P(SA) | */ P(KE) | P(ID), PT(HASH)#endif , EVENT_SA_REPLACE, quick_inR1_outI2 }, /* STATE_QUICK_R1: HDR*, HASH(3) --> done * Installs outbound IPsec SAs, routing, etc. */ { STATE_QUICK_R1, STATE_QUICK_R2 , SMF_ALL_AUTH | SMF_ENCRYPTED , P(HASH), LEMPTY, PT(NONE) , EVENT_SA_REPLACE, quick_inI2 }, /* STATE_QUICK_I2: can only happen due to lost packet */ { STATE_QUICK_I2, STATE_UNDEFINED , SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED | SMF_RETRANSMIT_ON_DUPLICATE , LEMPTY, LEMPTY, PT(NONE) , EVENT_NULL, unexpected }, /* STATE_QUICK_R2: can only happen due to lost packet */ { STATE_QUICK_R2, STATE_UNDEFINED , SMF_ALL_AUTH | SMF_ENCRYPTED , LEMPTY, LEMPTY, PT(NONE) , EVENT_NULL, unexpected }, /***** informational messages *****/ /* STATE_INFO: */ { STATE_INFO, STATE_UNDEFINED , SMF_ALL_AUTH , LEMPTY, LEMPTY, PT(NONE) , EVENT_NULL, informational }, /* STATE_INFO_PROTECTED: */ { STATE_INFO_PROTECTED, STATE_UNDEFINED , SMF_ALL_AUTH | SMF_ENCRYPTED , P(HASH), LEMPTY, PT(NONE) , EVENT_NULL, informational },#ifdef XAUTH { STATE_XAUTH_R0, STATE_XAUTH_R1 , SMF_ALL_AUTH | SMF_ENCRYPTED , P(ATTR) | P(HASH), P(VID), PT(NONE) , EVENT_NULL, xauth_inR0 }, /*Re-transmit may be done by previous state*/ { STATE_XAUTH_R1, STATE_MAIN_R3 , SMF_ALL_AUTH | SMF_ENCRYPTED , P(ATTR) | P(HASH), P(VID), PT(NONE) , EVENT_SA_REPLACE, xauth_inR1 },#if 0 /* for situation where there is XAUTH + ModeCFG */ { STATE_XAUTH_R2, STATE_XAUTH_R3 , SMF_ALL_AUTH | SMF_ENCRYPTED , P(ATTR) | P(HASH), P(VID), PT(NONE) , EVENT_SA_REPLACE, xauth_inR2 }, { STATE_XAUTH_R3, STATE_MAIN_R3 , SMF_ALL_AUTH | SMF_ENCRYPTED , P(ATTR) | P(HASH), P(VID), PT(NONE) , EVENT_SA_REPLACE, xauth_inR3 },#endif#endif#ifdef MODECFG/* MODE_CFG_x: * Case R0: Responder -> Initiator * <- Req(addr=0) * Reply(ad=x) -> * * Case R1: Set(addr=x) -> * <- Ack(ok) */ { STATE_MODE_CFG_R0, STATE_MODE_CFG_R1 , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY , P(ATTR) | P(HASH), P(VID), PT(HASH) , EVENT_SA_REPLACE, modecfg_inR0 }, { STATE_MODE_CFG_R1, STATE_MODE_CFG_R2 , SMF_ALL_AUTH | SMF_ENCRYPTED , P(ATTR) | P(HASH), P(VID), PT(HASH) , EVENT_SA_REPLACE, modecfg_inR1 }, { STATE_MODE_CFG_R2, STATE_UNDEFINED , SMF_ALL_AUTH | SMF_ENCRYPTED , LEMPTY, LEMPTY, PT(NONE) , EVENT_NULL, unexpected }, { STATE_MODE_CFG_I1, STATE_MAIN_I4 , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2 , P(ATTR) | P(HASH), P(VID), PT(HASH) , EVENT_SA_REPLACE, modecfg_inR1 },#endif#ifdef XAUTH { STATE_XAUTH_I0, STATE_XAUTH_I1 , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2 , P(ATTR) | P(HASH), P(VID), PT(HASH) , EVENT_SA_REPLACE, xauth_inI0 }, { STATE_XAUTH_I1, STATE_MAIN_I4 , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2 , P(ATTR) | P(HASH), P(VID), PT(HASH) , EVENT_SA_REPLACE, xauth_inI1 },#endif#undef P#undef PT};voidinit_demux(void){ /* fill ike_microcode_index: * make ike_microcode_index[s] point to first entry in * state_microcode_table for state s (backward scan makes this easier). * Check that table is in order -- catch coding errors. * For what it's worth, this routine is idempotent. */ const struct state_microcode *t; for (t = &state_microcode_table[elemsof(state_microcode_table) - 1];;) { passert(STATE_IKE_FLOOR <= t->state && t->state < STATE_IKE_ROOF); ike_microcode_index[t->state - STATE_IKE_FLOOR] = t; if (t == state_microcode_table) break; t--; passert(t[0].state <= t[1].state); }}/* Process any message on the MSG_ERRQUEUE * * This information is generated because of the IP_RECVERR socket option. * The API is sparsely documented, and may be LINUX-only, and only on * fairly recent versions at that (hence the conditional compilation). * * - ip(7) describes IP_RECVERR * - recvmsg(2) describes MSG_ERRQUEUE * - readv(2) describes iovec * - cmsg(3) describes how to process auxilliary messages * * ??? we should link this message with one we've sent * so that the diagnostic can refer to that negotiation. * * ??? how long can the messge be? * * ??? poll(2) has a very incomplete description of the POLL* events. * We assume that POLLIN, POLLOUT, and POLLERR are all we need to deal with * and that POLLERR will be on iff there is a MSG_ERRQUEUE message. * * We have to code around a couple of surprises: * * - Select can say that a socket is ready to read from, and * yet a read will hang. It turns out that a message available on the * MSG_ERRQUEUE will cause select to say something is pending, but * a normal read will hang. poll(2) can tell when a MSG_ERRQUEUE * message is pending. * * This is dealt with by calling check_msg_errqueue after select * has indicated that there is something to read, but before the * read is performed. check_msg_errqueue will return TRUE if there * is something left to read. * * - A write to a socket may fail because there is a pending MSG_ERRQUEUE * message, without there being anything wrong with the write. This * makes for confusing diagnostics. * * To avoid this, we call check_msg_errqueue before a write. True, * there is a race condition (a MSG_ERRQUEUE message might arrive * between the check and the write), but we should eliminate many * of the problematic events. To narrow the window, the poll(2) * will await until an event happens (in the case or a write, * POLLOUT; this should be benign for POLLIN). */#if defined(IP_RECVERR) && defined(MSG_ERRQUEUE)static boolcheck_msg_errqueue(const struct iface *ifp, short interest){ struct pollfd pfd; pfd.fd = ifp->fd; pfd.events = interest | POLLPRI | POLLOUT; while (pfd.revents = 0 , poll(&pfd, 1, -1) > 0 && (pfd.revents & POLLERR)) { u_int8_t buffer[3000]; /* hope that this is big enough */ union { struct sockaddr sa; struct sockaddr_in sa_in4; struct sockaddr_in6 sa_in6; } from; int from_len = sizeof(from); int packet_len; struct msghdr emh; struct iovec eiov; union { /* force alignment (not documented as necessary) */ struct cmsghdr ecms; /* how much space is enough? */ unsigned char space[256]; } ecms_buf; struct cmsghdr *cm; char fromstr[sizeof(" for message to port 65536") + INET6_ADDRSTRLEN]; struct state *sender = NULL; zero(&from.sa); from_len = sizeof(from); emh.msg_name = &from.sa; /* ??? filled in? */ emh.msg_namelen = sizeof(from); emh.msg_iov = &eiov; emh.msg_iovlen = 1; emh.msg_control = &ecms_buf; emh.msg_controllen = sizeof(ecms_buf); emh.msg_flags = 0; eiov.iov_base = buffer; /* see readv(2) */ eiov.iov_len = sizeof(buffer); packet_len = recvmsg(ifp->fd, &emh, MSG_ERRQUEUE); if (packet_len == -1) { log_errno((e, "recvmsg(,, MSG_ERRQUEUE) on %s failed in comm_handle" , ifp->rname)); break; } else if (packet_len == sizeof(buffer)) { openswan_log("MSG_ERRQUEUE message longer than %lu bytes; truncated" , (unsigned long) sizeof(buffer)); } else { sender = find_sender((size_t) packet_len, buffer); } DBG_cond_dump(DBG_ALL, "rejected packet:\n", buffer, packet_len); DBG_cond_dump(DBG_ALL, "control:\n", emh.msg_control, emh.msg_controllen); /* ??? Andi Kleen <ak@suse.de> and misc documentation * suggests that name will have the original destination * of the packet. We seem to see msg_namelen == 0. * Andi says that this is a kernel bug and has fixed it. * Perhaps in 2.2.18/2.4.0. */ passert(emh.msg_name == &from.sa); DBG_cond_dump(DBG_ALL, "name:\n", emh.msg_name , emh.msg_namelen); fromstr[0] = '\0'; /* usual case :-( */ switch (from.sa.sa_family) { char as[INET6_ADDRSTRLEN]; case AF_INET: if (emh.msg_namelen == sizeof(struct sockaddr_in)) snprintf(fromstr, sizeof(fromstr) , " for message to %s port %u" , inet_ntop(from.sa.sa_family , &from.sa_in4.sin_addr, as, sizeof(as)) , ntohs(from.sa_in4.sin_port)); break; case AF_INET6: if (emh.msg_namelen == sizeof(struct sockaddr_in6)) snprintf(fromstr, sizeof(fromstr) , " for message to %s port %u" , inet_ntop(from.sa.sa_family , &from.sa_in6.sin6_addr, as, sizeof(as)) , ntohs(from.sa_in6.sin6_port)); break; } for (cm = CMSG_FIRSTHDR(&emh) ; cm != NULL ; cm = CMSG_NXTHDR(&emh,cm)) { if (cm->cmsg_level == SOL_IP && cm->cmsg_type == IP_RECVERR) { /* ip(7) and recvmsg(2) specify: * ee_origin is SO_EE_ORIGIN_ICMP for ICMP * or SO_EE_ORIGIN_LOCAL for locally generated errors. * ee_type and ee_code are from the ICMP header. * ee_info is the discovered MTU for EMSGSIZE errors * ee_data is not used. * * ??? recvmsg(2) says "SOCK_EE_OFFENDER" but * means "SO_EE_OFFENDER". The OFFENDER is really * the router that complained. As such, the port * is meaningless. */ /* ??? cmsg(3) claims that CMSG_DATA returns * void *, but RFC 2292 and /usr/include/bits/socket.h * say unsigned char *. The manual is being fixed. */ struct sock_extended_err *ee = (void *)CMSG_DATA(cm); const char *offstr = "unspecified"; char offstrspace[INET6_ADDRSTRLEN]; char orname[50]; if (cm->cmsg_len > CMSG_LEN(sizeof(struct sock_extended_err))) { const struct sockaddr *offender = SO_EE_OFFENDER(ee); switch (offender->sa_family) { case AF_INET: offstr = inet_ntop(offender->sa_family , &((const struct sockaddr_in *)offender)->sin_addr , offstrspace, sizeof(offstrspace)); break; case AF_INET6: offstr = inet_ntop(offender->sa_family , &((const struct sockaddr_in6 *)offender)->sin6_addr , offstrspace, sizeof(offstrspace)); break; default: offstr = "unknown"; break; } } switch (ee->ee_origin) { case SO_EE_ORIGIN_NONE: snprintf(orname, sizeof(orname), "none"); break; case SO_EE_ORIGIN_LOCAL: snprintf(orname, sizeof(orname), "local"); break; case SO_EE_ORIGIN_ICMP: snprintf(orname, sizeof(orname) , "ICMP type %d code %d (not authenticated)" , ee->ee_type, ee->ee_code ); 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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -