/********************************************************************** * %FUNCTION: peer_find * %ARGUMENTS: * addr -- IP address of peer * hostname -- AVP peer hostname * %RETURNS: * A pointer to the peer with given IP address, or NULL if not found. * %DESCRIPTION: * Searches peer hash table for specified peer. ***********************************************************************/ l2tp_peer * l2tp_peer_find(struct sockaddr_in *addr, char const *peername) { void *cursor; l2tp_peer *peer = NULL; l2tp_peer *candidate = NULL; char addr1_str[16], addr2_str[16]; for (candidate = hash_start(&all_peers, &cursor); candidate ; candidate = hash_next(&all_peers, &cursor)) { unsigned long mask = candidate->mask_bits ? htonl(0xFFFFFFFFUL << (32 - candidate->mask_bits)) : 0; strcpy(addr1_str, inet_ntoa(addr->sin_addr)); strcpy(addr2_str, inet_ntoa(candidate->addr.sin_addr)); DBG(l2tp_db(DBG_TUNNEL, "l2tp_peer_find(%s) examining peer %s/%d\n", addr1_str, addr2_str, candidate->mask_bits)); if ((candidate->addr.sin_addr.s_addr & mask) == (addr->sin_addr.s_addr & mask) && (!peername || !(candidate->peername[0]) || !strcmp(peername,candidate->peername))) { if (peer == NULL) { peer = candidate; } else { if (peer->mask_bits < candidate->mask_bits) peer = candidate; } } } strcpy(addr1_str, inet_ntoa(addr->sin_addr)); if (peer != NULL) strcpy(addr2_str, inet_ntoa(peer->addr.sin_addr)); DBG(l2tp_db(DBG_TUNNEL, "l2tp_peer_find(%s) found %s/%d\n", addr1_str, peer == NULL ? "NULL" : addr2_str, peer == NULL ? -1 : peer->mask_bits)); return peer; }
/********************************************************************** * %FUNCTION: session_free * %ARGUMENTS: * ses -- a session to free * %RETURNS: * Nothing * %DESCRIPTION: * Frees a session, closing down all resources associated with it. ***********************************************************************/ void l2tp_session_free(l2tp_session *ses, char const *reason) { session_set_state(ses, SESSION_IDLE); DBG(l2tp_db(DBG_SESSION, "session_free(%s) %s\n", l2tp_debug_session_to_str(ses), reason)); if (ses->call_ops && ses->call_ops->close) { ses->call_ops->close(ses, reason); } memset(ses, 0, sizeof(l2tp_session)); free(ses); }
/********************************************************************** * %FUNCTION: auth_gen_response * %ARGUMENTS: * msg_type -- message type * secret -- secret to use * challenge -- challenge received from peer * chal_len -- length of challenge * buf -- buffer in which to place 16-byte response * %RETURNS: * Nothing * %DESCRIPTION: * Computes a response for the challenge using "secret" ***********************************************************************/ void l2tp_auth_gen_response(uint16_t msg_type, char const *secret, unsigned char const *challenge, size_t chal_len, unsigned char buf[16]) { struct MD5Context ctx; unsigned char id = (unsigned char) msg_type; MD5Init(&ctx); MD5Update(&ctx, &id, 1); MD5Update(&ctx, (unsigned char *) secret, strlen(secret)); MD5Update(&ctx, challenge, chal_len); MD5Final(buf, &ctx); DBG(l2tp_db(DBG_AUTH, "auth_gen_response(secret=%s) -> %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", secret, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15])); }