int gtpie_gettv1(union gtpie_member* ie[], int type, int instance, uint8_t *dst){ int ien; ien = gtpie_getie(ie, type, instance); if (ien>=0) *dst = ntoh8(ie[ien]->tv1.v); else return EOF; return 0; }
void recv_handler_done (BSocksClient *o, int data_len) { ASSERT(data_len >= 0) ASSERT(data_len <= o->control.recv_total - o->control.recv_len) DebugObject_Access(&o->d_obj); o->control.recv_len += data_len; if (o->control.recv_len < o->control.recv_total) { do_receive(o); return; } switch (o->state) { case STATE_SENT_HELLO: { BLog(BLOG_DEBUG, "received hello"); struct socks_server_hello imsg; memcpy(&imsg, o->buffer, sizeof(imsg)); if (ntoh8(imsg.ver) != SOCKS_VERSION) { BLog(BLOG_NOTICE, "wrong version"); goto fail; } size_t auth_index; for (auth_index = 0; auth_index < o->num_auth_info; auth_index++) { if (o->auth_info[auth_index].auth_type == ntoh8(imsg.method)) { break; } } if (auth_index == o->num_auth_info) { BLog(BLOG_NOTICE, "server didn't accept any authentication method"); goto fail; } const struct BSocksClient_auth_info *ai = &o->auth_info[auth_index]; switch (ai->auth_type) { case SOCKS_METHOD_NO_AUTHENTICATION_REQUIRED: { BLog(BLOG_DEBUG, "no authentication"); auth_finished(o); } break; case SOCKS_METHOD_USERNAME_PASSWORD: { BLog(BLOG_DEBUG, "password authentication"); if (ai->password.username_len == 0 || ai->password.username_len > 255 || ai->password.password_len == 0 || ai->password.password_len > 255 ) { BLog(BLOG_NOTICE, "invalid username/password length"); goto fail; } // allocate password packet bsize_t size = bsize_fromsize(1 + 1 + ai->password.username_len + 1 + ai->password.password_len); if (!reserve_buffer(o, size)) { goto fail; } // write password packet char *ptr = o->buffer; *ptr++ = 1; *ptr++ = ai->password.username_len; memcpy(ptr, ai->password.username, ai->password.username_len); ptr += ai->password.username_len; *ptr++ = ai->password.password_len; memcpy(ptr, ai->password.password, ai->password.password_len); ptr += ai->password.password_len; // start sending PacketPassInterface_Sender_Send(o->control.send_if, (uint8_t *)o->buffer, size.value); // set state o->state = STATE_SENDING_PASSWORD; } break; default: ASSERT(0); } } break; case STATE_SENT_REQUEST: { BLog(BLOG_DEBUG, "received reply header"); struct socks_reply_header imsg; memcpy(&imsg, o->buffer, sizeof(imsg)); if (ntoh8(imsg.ver) != SOCKS_VERSION) { BLog(BLOG_NOTICE, "wrong version"); goto fail; } if (ntoh8(imsg.rep) != SOCKS_REP_SUCCEEDED) { BLog(BLOG_NOTICE, "reply not successful"); goto fail; } int addr_len; switch (ntoh8(imsg.atyp)) { case SOCKS_ATYP_IPV4: addr_len = sizeof(struct socks_addr_ipv4); break; case SOCKS_ATYP_IPV6: addr_len = sizeof(struct socks_addr_ipv6); break; default: BLog(BLOG_NOTICE, "reply has unknown address type"); goto fail; } // receive the rest of the reply start_receive(o, (uint8_t *)o->buffer + sizeof(imsg), addr_len); // set state o->state = STATE_RECEIVED_REPLY_HEADER; } break; case STATE_SENT_PASSWORD: { BLog(BLOG_DEBUG, "received password reply"); if (o->buffer[0] != 1) { BLog(BLOG_NOTICE, "password reply has unknown version"); goto fail; } if (o->buffer[1] != 0) { BLog(BLOG_NOTICE, "password reply is negative"); goto fail; } auth_finished(o); } break; case STATE_RECEIVED_REPLY_HEADER: { BLog(BLOG_DEBUG, "received reply rest"); // free buffer BFree(o->buffer); o->buffer = NULL; // free control I/O free_control_io(o); // init up I/O init_up_io(o); // set state o->state = STATE_UP; // call handler o->handler(o->user, BSOCKSCLIENT_EVENT_UP); return; } break; default: ASSERT(0); } return; fail: report_error(o, BSOCKSCLIENT_EVENT_ERROR); }
/*** decaps_gre ***************************************************************/ int decaps_gre (int fd, callback_t callback, int cl) { unsigned char buffer[PACKET_MAX + 64 /*ip header*/]; struct pptp_gre_header *header; int status, ip_len = 0; static int first = 1; unsigned int headersize; unsigned int payload_len; u_int32_t seq; if ((status = read (fd, buffer, sizeof(buffer))) <= 0) { warn("short read (%d): %s", status, strerror(errno)); stats.rx_errors++; return -1; } /* strip off IP header, if present */ if ((buffer[0] & 0xF0) == 0x40) ip_len = (buffer[0] & 0xF) * 4; header = (struct pptp_gre_header *)(buffer + ip_len); /* verify packet (else discard) */ if ( /* version should be 1 */ ((ntoh8(header->ver) & 0x7F) != PPTP_GRE_VER) || /* PPTP-GRE protocol for PPTP */ (ntoh16(header->protocol) != PPTP_GRE_PROTO)|| /* flag C should be clear */ PPTP_GRE_IS_C(ntoh8(header->flags)) || /* flag R should be clear */ PPTP_GRE_IS_R(ntoh8(header->flags)) || /* flag K should be set */ (!PPTP_GRE_IS_K(ntoh8(header->flags))) || /* routing and recursion ctrl = 0 */ ((ntoh8(header->flags)&0xF) != 0)) { /* if invalid, discard this packet */ warn("Discarding GRE: %X %X %X %X %X %X", ntoh8(header->ver)&0x7F, ntoh16(header->protocol), PPTP_GRE_IS_C(ntoh8(header->flags)), PPTP_GRE_IS_R(ntoh8(header->flags)), PPTP_GRE_IS_K(ntoh8(header->flags)), ntoh8(header->flags) & 0xF); stats.rx_invalid++; return 0; } /* silently discard packets not for this call */ if (ntoh16(header->call_id) != pptp_gre_call_id) return 0; /* test if acknowledgement present */ if (PPTP_GRE_IS_A(ntoh8(header->ver))) { u_int32_t ack = (PPTP_GRE_IS_S(ntoh8(header->flags)))? header->ack:header->seq; /* ack in different place if S = 0 */ ack = ntoh32( ack); if (ack > ack_recv) ack_recv = ack; /* also handle sequence number wrap-around */ if (WRAPPED(ack,ack_recv)) ack_recv = ack; if (ack_recv == stats.pt.seq) { int rtt = time_now_usecs() - stats.pt.time; stats.rtt = (stats.rtt + rtt) / 2; } } /* test if payload present */ if (!PPTP_GRE_IS_S(ntoh8(header->flags))) return 0; /* ack, but no payload */ headersize = sizeof(*header); payload_len = ntoh16(header->payload_len); seq = ntoh32(header->seq); /* no ack present? */ if (!PPTP_GRE_IS_A(ntoh8(header->ver))) headersize -= sizeof(header->ack); /* check for incomplete packet (length smaller than expected) */ if (status - headersize < payload_len) { warn("discarding truncated packet (expected %d, got %d bytes)", payload_len, status - headersize); stats.rx_truncated++; return 0; } /* check for expected sequence number */ if ( first || (seq == seq_recv + 1)) { /* wrap-around safe */ if ( log_level >= 2 ) log("accepting packet %d", seq); stats.rx_accepted++; first = 0; seq_recv = seq; return callback(cl, buffer + ip_len + headersize, payload_len); /* out of order, check if the number is too low and discard the packet. * (handle sequence number wrap-around, and try to do it right) */ } else if ( seq < seq_recv + 1 || WRAPPED(seq_recv, seq) ) { if ( log_level >= 1 ) log("discarding duplicate or old packet %d (expecting %d)", seq, seq_recv + 1); stats.rx_underwin++; /* sequence number too high, is it reasonably close? */ } else if ( seq < seq_recv + MISSING_WINDOW || WRAPPED(seq, seq_recv + MISSING_WINDOW) ) { stats.rx_buffered++; if ( log_level >= 1 ) log("%s packet %d (expecting %d, lost or reordered)", disable_buffer ? "accepting" : "buffering", seq, seq_recv+1); if ( disable_buffer ) { seq_recv = seq; stats.rx_lost += seq - seq_recv - 1; return callback(cl, buffer + ip_len + headersize, payload_len); } else { pqueue_add(seq, buffer + ip_len + headersize, payload_len); } /* no, packet must be discarded */ } else { if ( log_level >= 1 ) warn("discarding bogus packet %d (expecting %d)", seq, seq_recv + 1); stats.rx_overwin++; } return 0; }
int gtpie_decaps(union gtpie_member* ie[], int version, void *pack, unsigned len) { int i; int j = 0; unsigned char *p; unsigned char *end; end = (unsigned char*) pack + len; p = pack; memset(ie, 0, sizeof(union gtpie_member *) * GTPIE_SIZE); while ((p<end) && (j<GTPIE_SIZE)) { if (GTPIE_DEBUG) { printf("The packet looks like this:\n"); for( i=0; i<(end-p); i++) { printf("%02x ", (unsigned char)*(char *)(p+i)); if (!((i+1)%16)) printf("\n"); }; printf("\n"); } switch (*p) { case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */ case GTPIE_REORDER: case GTPIE_MAP_CAUSE: case GTPIE_MS_VALIDATED: case GTPIE_RECOVERY: case GTPIE_SELECTION_MODE: case GTPIE_TEARDOWN: case GTPIE_NSAPI: case GTPIE_RANAP_CAUSE: case GTPIE_RP_SMS: case GTPIE_RP: case GTPIE_MS_NOT_REACH: if (j<GTPIE_SIZE) { ie[j] = (union gtpie_member*) p; if (GTPIE_DEBUG) printf("GTPIE TV1 found. Type %d, value %d\n", ie[j]->tv1.t, ie[j]->tv1.v); p+= 1 + 1; j++; } break; case GTPIE_FL_DI: /* TV GTPIE types with value length 2 or 4 */ case GTPIE_FL_C: if (version != 0) { if (j<GTPIE_SIZE) { /* GTPIE_TEI_DI & GTPIE_TEI_C with length 4 */ /* case GTPIE_TEI_DI: gtp1 */ /* case GTPIE_TEI_C: gtp1 */ ie[j] = (union gtpie_member*) p; if (GTPIE_DEBUG) printf("GTPIE TV 4 found. Type %d, value %d\n", ie[j]->tv4.t, ie[j]->tv4.v); p+= 1 + 4; j++; } break; } case GTPIE_PFI: /* TV GTPIE types with value length 2 */ case GTPIE_CHARGING_C: case GTPIE_TRACE_REF: case GTPIE_TRACE_TYPE: if (j<GTPIE_SIZE) { ie[j] = (union gtpie_member*) p; if (GTPIE_DEBUG) printf("GTPIE TV2 found. Type %d, value %d\n", ie[j]->tv2.t, ie[j]->tv2.v); p+= 1 + 2; j++; } break; case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */ case GTPIE_P_TMSI_S: if (j<GTPIE_SIZE) { ie[j] = (union gtpie_member*) p; if (GTPIE_DEBUG) printf("GTPIE TV 3 found. Type %d, value %d, %d, %d\n", ie[j]->tv0.t, ie[j]->tv0.v[0], ie[j]->tv0.v[1], ie[j]->tv0.v[2]); p+= 1 + 3; j++; } break; case GTPIE_TLLI: /* TV GTPIE types with value length 4 */ case GTPIE_P_TMSI: case GTPIE_CHARGING_ID: /* case GTPIE_TEI_DI: Handled by GTPIE_FL_DI */ /* case GTPIE_TEI_C: Handled by GTPIE_FL_DI */ if (j<GTPIE_SIZE) { ie[j] = (union gtpie_member*) p; if (GTPIE_DEBUG) printf("GTPIE TV 4 found. Type %d, value %d\n", ie[j]->tv4.t, ie[j]->tv4.v); p+= 1 + 4; j++; } break; case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */ if (j<GTPIE_SIZE) { ie[j] = (union gtpie_member*) p; if (GTPIE_DEBUG) printf("GTPIE TV 5 found. Type %d\n", ie[j]->tv0.t); p+= 1 + 5; j++; } break; case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */ if (j<GTPIE_SIZE) { ie[j] = (union gtpie_member*) p; if (GTPIE_DEBUG) printf("GTPIE TV 7 found. Type %d\n", ie[j]->tv0.t); p+= 1 + 7; j++; } break; case GTPIE_IMSI: /* TV GTPIE types with value length 8 */ case GTPIE_RAI: if (j<GTPIE_SIZE) { ie[j] = (union gtpie_member*) p; if (GTPIE_DEBUG) printf("GTPIE TV 8 found. Type %d, value 0x%llx\n", ie[j]->tv0.t, ie[j]->tv8.v); p+= 1 + 8; j++; } break; case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */ if (j<GTPIE_SIZE) { ie[j] = (union gtpie_member*) p; if (GTPIE_DEBUG) printf("GTPIE TV 28 found. Type %d\n", ie[j]->tv0.t); p+= 1 + 28; j++; } break; case GTPIE_EXT_HEADER_T: /* GTP extension header */ if (j<GTPIE_SIZE) { ie[j] = (union gtpie_member*) p; if (GTPIE_DEBUG) printf("GTPIE GTP extension header found. Type %d\n", ie[j]->ext.t); p+= 2 + ntoh8(ie[j]->ext.l); j++; } break; case GTPIE_EUA: /* TLV GTPIE types with variable length */ case GTPIE_MM_CONTEXT: case GTPIE_PDP_CONTEXT: case GTPIE_APN: case GTPIE_PCO: case GTPIE_GSN_ADDR: case GTPIE_MSISDN: case GTPIE_QOS_PROFILE: case GTPIE_AUTH_QUINTUP: case GTPIE_TFT: case GTPIE_TARGET_INF: case GTPIE_UTRAN_TRANS: case GTPIE_RAB_SETUP: case GTPIE_TRIGGER_ID: case GTPIE_OMC_ID: case GTPIE_CHARGING_ADDR: case GTPIE_PRIVATE: if (j<GTPIE_SIZE) { ie[j] = (union gtpie_member*) p; if (GTPIE_DEBUG) printf("GTPIE TLV found. Type %d\n", ie[j]->tlv.t); p+= 3 + ntoh16(ie[j]->tlv.l); j++; } break; default: if (GTPIE_DEBUG) printf("GTPIE something unknown. Type %d\n", *p); return EOF; /* We received something unknown */ } } if (p==end) { if (GTPIE_DEBUG) printf("GTPIE normal return. %lx %lx\n", (unsigned long) p, (unsigned long) end); return 0; /* We landed at the end of the packet: OK */ } else if (!(j<GTPIE_SIZE)) { if (GTPIE_DEBUG) printf("GTPIE too many elements.\n"); return EOF; /* We received too many information elements */ } else { if (GTPIE_DEBUG) printf("GTPIE exceeded end of packet. %lx %lx\n", (unsigned long) p, (unsigned long) end); return EOF; /* We exceeded the end of the packet: Error */ } }
/*** pptp_dispatch_ctrl_packet ************************************************/ int ctrlp_disp(PPTP_CONN * conn, void * buffer, size_t size) { struct pptp_header *header = (struct pptp_header *)buffer; u_int8_t close_reason = PPTP_STOP_NONE; assert(conn && conn->call); assert(buffer); assert(ntoh32(header->magic) == PPTP_MAGIC); assert(ntoh16(header->length) == size); assert(ntoh16(header->pptp_type) == PPTP_MESSAGE_CONTROL); if (size < PPTP_CTRL_SIZE(ntoh16(header->ctrl_type))) { log("Invalid packet received [type: %d; length: %d].", (int) ntoh16(header->ctrl_type), (int) size); return 0; } switch (ntoh16(header->ctrl_type)) { /* ----------- STANDARD Start-Session MESSAGES ------------ */ case PPTP_START_CTRL_CONN_RQST: { struct pptp_start_ctrl_conn *packet = (struct pptp_start_ctrl_conn *) buffer; struct pptp_start_ctrl_conn reply = { PPTP_HEADER_CTRL(PPTP_START_CTRL_CONN_RPLY), hton16(PPTP_VERSION), 0, 0, hton32(PPTP_FRAME_CAP), hton32(PPTP_BEARER_CAP), hton16(PPTP_MAX_CHANNELS), hton16(PPTP_FIRMWARE_VERSION), PPTP_HOSTNAME, PPTP_VENDOR }; int idx, rc; log("Received Start Control Connection Request"); /* fix this packet, if necessary */ idx = get_quirk_index(); if (idx != -1 && pptp_fixups[idx].start_ctrl_conn) { if ((rc = pptp_fixups[idx].start_ctrl_conn(&reply))) warn("calling the start_ctrl_conn hook failed (%d)", rc); } if (conn->conn_state == CONN_IDLE) { if (ntoh16(packet->version) < PPTP_VERSION) { /* Can't support this (earlier) PPTP_VERSION */ reply.version = packet->version; /* protocol version not supported */ reply.result_code = hton8(5); pptp_send_ctrl_packet(conn, &reply, sizeof(reply)); pptp_reset_timer(); /* give sender a chance for a retry */ } else { /* same or greater version */ if (pptp_send_ctrl_packet(conn, &reply, sizeof(reply))) { conn->conn_state = CONN_ESTABLISHED; log("server connection ESTABLISHED."); pptp_reset_timer(); } } } break; } case PPTP_START_CTRL_CONN_RPLY: { struct pptp_start_ctrl_conn *packet = (struct pptp_start_ctrl_conn *) buffer; log("Received Start Control Connection Reply"); if (conn->conn_state == CONN_WAIT_CTL_REPLY) { /* XXX handle collision XXX [see rfc] */ if (ntoh16(packet->version) != PPTP_VERSION) { if (conn->callback != NULL) conn->callback(conn, CONN_OPEN_FAIL); close_reason = PPTP_STOP_PROTOCOL; goto pptp_conn_close; } if (ntoh8(packet->result_code) != 1 && /* J'ai change le if () afin que la connection ne se ferme * pas pour un "rien" :p [email protected] - * * Don't close the connection if the result code is zero * (feature found in certain ADSL modems) */ ntoh8(packet->result_code) != 0) { log("Negative reply received to our Start Control " "Connection Request"); ctrlp_error(packet->result_code, packet->error_code, -1, pptp_start_ctrl_conn_rply, MAX_START_CTRL_CONN_REPLY); if (conn->callback != NULL) conn->callback(conn, CONN_OPEN_FAIL); close_reason = PPTP_STOP_PROTOCOL; goto pptp_conn_close; } conn->conn_state = CONN_ESTABLISHED; /* log session properties */ conn->version = ntoh16(packet->version); conn->firmware_rev = ntoh16(packet->firmware_rev); memcpy(conn->hostname, packet->hostname, sizeof(conn->hostname)); memcpy(conn->vendor, packet->vendor, sizeof(conn->vendor)); pptp_reset_timer(); /* 60 seconds until keep-alive */ log("Client connection established."); if (conn->callback != NULL) conn->callback(conn, CONN_OPEN_DONE); } /* else goto pptp_conn_close; */ break; } /* ----------- STANDARD Stop-Session MESSAGES ------------ */ case PPTP_STOP_CTRL_CONN_RQST: { /* conn_state should be CONN_ESTABLISHED, but it could be * something else */ struct pptp_stop_ctrl_conn reply = { PPTP_HEADER_CTRL(PPTP_STOP_CTRL_CONN_RPLY), hton8(1), hton8(PPTP_GENERAL_ERROR_NONE), 0 }; log("Received Stop Control Connection Request."); if (conn->conn_state == CONN_IDLE) break; if (pptp_send_ctrl_packet(conn, &reply, sizeof(reply))) { if (conn->callback != NULL) conn->callback(conn, CONN_CLOSE_RQST); conn->conn_state = CONN_IDLE; return -1; } break; } case PPTP_STOP_CTRL_CONN_RPLY: { log("Received Stop Control Connection Reply."); /* conn_state should be CONN_WAIT_STOP_REPLY, but it * could be something else */ if (conn->conn_state == CONN_IDLE) break; conn->conn_state = CONN_IDLE; return -1; } /* ----------- STANDARD Echo/Keepalive MESSAGES ------------ */ case PPTP_ECHO_RPLY: { struct pptp_echo_rply *packet = (struct pptp_echo_rply *) buffer; logecho( PPTP_ECHO_RPLY); if ((conn->ka_state == KA_OUTSTANDING) && (ntoh32(packet->identifier) == conn->ka_id)) { conn->ka_id++; conn->ka_state = KA_NONE; pptp_reset_timer(); } break; } case PPTP_ECHO_RQST: { struct pptp_echo_rqst *packet = (struct pptp_echo_rqst *) buffer; struct pptp_echo_rply reply = { PPTP_HEADER_CTRL(PPTP_ECHO_RPLY), packet->identifier, /* skip hton32(ntoh32(id)) */ hton8(1), hton8(PPTP_GENERAL_ERROR_NONE), 0 }; logecho( PPTP_ECHO_RQST); pptp_send_ctrl_packet(conn, &reply, sizeof(reply)); pptp_reset_timer(); break; } /* ----------- OUTGOING CALL MESSAGES ------------ */ case PPTP_OUT_CALL_RQST: { struct pptp_out_call_rqst *packet = (struct pptp_out_call_rqst *)buffer; struct pptp_out_call_rply reply = { PPTP_HEADER_CTRL(PPTP_OUT_CALL_RPLY), 0 /* callid */, packet->call_id, 1, PPTP_GENERAL_ERROR_NONE, 0, hton32(PPTP_CONNECT_SPEED), hton16(PPTP_WINDOW), hton16(PPTP_DELAY), 0 }; log("Received Outgoing Call Request."); /* XXX PAC: eventually this should make an outgoing call. XXX */ reply.result_code = hton8(7); /* outgoing calls verboten */ pptp_send_ctrl_packet(conn, &reply, sizeof(reply)); break; } case PPTP_OUT_CALL_RPLY: { struct pptp_out_call_rply *packet = (struct pptp_out_call_rply *)buffer; PPTP_CALL * call; u_int16_t callid = ntoh16(packet->call_id_peer); log("Received Outgoing Call Reply."); if (!vector_search(conn->call, (int) callid, &call)) { log("PPTP_OUT_CALL_RPLY received for non-existant call: " "peer call ID (us) %d call ID (them) %d.", callid, ntoh16(packet->call_id)); break; } if (call->call_type != PPTP_CALL_PNS) { log("Ack! How did this call_type get here?"); /* XXX? */ break; } if (call->state.pns != PNS_WAIT_REPLY) { warn("Unexpected(?) Outgoing Call Reply will be ignored."); break; } /* check for errors */ if (packet->result_code != 1) { /* An error. Log it verbosely. */ log("Our outgoing call request [callid %d] has not been " "accepted.", (int) callid); ctrlp_error(packet->result_code, packet->error_code, packet->cause_code, pptp_out_call_reply_result, MAX_OUT_CALL_REPLY_RESULT); call->state.pns = PNS_IDLE; if (call->callback != NULL) call->callback(conn, call, CALL_OPEN_FAIL); pptp_call_destroy(conn, call); } else { /* connection established */ call->state.pns = PNS_ESTABLISHED; call->peer_call_id = ntoh16(packet->call_id); call->speed = ntoh32(packet->speed); pptp_reset_timer(); /* call pptp_set_link. unless the user specified a quirk and this quirk has a set_link hook, this is a noop */ pptp_set_link(conn, call->peer_call_id); if (call->callback != NULL) call->callback(conn, call, CALL_OPEN_DONE); log("Outgoing call established (call ID %u, peer's " "call ID %u).\n", call->call_id, call->peer_call_id); } break; } /* ----------- INCOMING CALL MESSAGES ------------ */ /* XXX write me XXX */ /* ----------- CALL CONTROL MESSAGES ------------ */ case PPTP_CALL_CLEAR_RQST: { struct pptp_call_clear_rqst *packet = (struct pptp_call_clear_rqst *)buffer; struct pptp_call_clear_ntfy reply = { PPTP_HEADER_CTRL(PPTP_CALL_CLEAR_NTFY), packet->call_id, 1, PPTP_GENERAL_ERROR_NONE, 0, 0, {0} }; log("Received Call Clear Request."); if (vector_contains(conn->call, ntoh16(packet->call_id))) { PPTP_CALL * call; vector_search(conn->call, ntoh16(packet->call_id), &call); if (call->callback != NULL) call->callback(conn, call, CALL_CLOSE_RQST); pptp_send_ctrl_packet(conn, &reply, sizeof(reply)); pptp_call_destroy(conn, call); log("Call closed (RQST) (call id %d)", (int) call->call_id); } break; } case PPTP_CALL_CLEAR_NTFY: { struct pptp_call_clear_ntfy *packet = (struct pptp_call_clear_ntfy *)buffer; log("Call disconnect notification received (call id %d)", ntoh16(packet->call_id)); if (vector_contains(conn->call, ntoh16(packet->call_id))) { PPTP_CALL * call; ctrlp_error(packet->result_code, packet->error_code, packet->cause_code, pptp_call_disc_ntfy, MAX_CALL_DISC_NTFY); vector_search(conn->call, ntoh16(packet->call_id), &call); pptp_call_destroy(conn, call); } /* XXX we could log call stats here XXX */ /* XXX not all servers send this XXX */ break; } case PPTP_SET_LINK_INFO: { /* I HAVE NO CLUE WHAT TO DO IF send_accm IS NOT 0! */ /* this is really dealt with in the HDLC deencapsulation, anyway. */ struct pptp_set_link_info *packet = (struct pptp_set_link_info *)buffer; /* log it. */ log("PPTP_SET_LINK_INFO received from peer_callid %u", (unsigned int) ntoh16(packet->call_id_peer)); log(" send_accm is %08lX, recv_accm is %08lX", (unsigned long) ntoh32(packet->send_accm), (unsigned long) ntoh32(packet->recv_accm)); if (!(ntoh32(packet->send_accm) == 0 && ntoh32(packet->recv_accm) == 0)) warn("Non-zero Async Control Character Maps are not supported!"); break; } default: log("Unrecognized Packet %d received.", (int) ntoh16(((struct pptp_header *)buffer)->ctrl_type)); /* goto pptp_conn_close; */ break; } return 0; pptp_conn_close: warn("pptp_conn_close(%d)", (int) close_reason); pptp_conn_close(conn, close_reason); return 0; }
static void recv_if_handler_done (BArpProbe *o, int data_len) { DebugObject_Access(&o->d_obj); ASSERT(data_len >= 0) ASSERT(data_len <= sizeof(struct arp_packet)) // receive next packet PacketRecvInterface_Receiver_Recv(o->recv_if, (uint8_t *)&o->recv_packet); if (data_len != sizeof(struct arp_packet)) { BLog(BLOG_WARNING, "receive: wrong size"); return; } struct arp_packet *arp = &o->recv_packet; if (ntoh16(arp->hardware_type) != ARP_HARDWARE_TYPE_ETHERNET) { BLog(BLOG_WARNING, "receive: wrong hardware type"); return; } if (ntoh16(arp->protocol_type) != ETHERTYPE_IPV4) { BLog(BLOG_WARNING, "receive: wrong protocol type"); return; } if (ntoh8(arp->hardware_size) != 6) { BLog(BLOG_WARNING, "receive: wrong hardware size"); return; } if (ntoh8(arp->protocol_size) != 4) { BLog(BLOG_WARNING, "receive: wrong protocol size"); return; } if (ntoh16(arp->opcode) != ARP_OPCODE_REPLY) { return; } if (arp->sender_ip != o->addr) { return; } int old_state = o->state; // set minus one missed o->num_missed = -1; // set timer BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_EXIST_WAITSEND); // set state exist o->state = STATE_EXIST; // report exist if needed if (old_state == STATE_INITIAL || old_state == STATE_NOEXIST) { o->handler(o->user, BARPPROBE_EVENT_EXIST); return; } }