Esempio n. 1
0
int gtpie_tv1(void *p, unsigned int *length, unsigned int size, uint8_t t, uint8_t v) {
  if ((*length + 2) >= size) return 1;
  ((union gtpie_member*) (p + *length))->tv1.t = hton8(t);
  ((union gtpie_member*) (p + *length))->tv1.v = hton8(v);
  *length += 2;
  return 0;
}
Esempio n. 2
0
static void send_request (BArpProbe *o)
{
    if (o->send_sending) {
        BLog(BLOG_ERROR, "cannot send packet while another packet is being sent!");
        return;
    }
    
    // build packet
    struct arp_packet *arp = &o->send_packet;
    arp->hardware_type = hton16(ARP_HARDWARE_TYPE_ETHERNET);
    arp->protocol_type = hton16(ETHERTYPE_IPV4);
    arp->hardware_size = hton8(6);
    arp->protocol_size = hton8(4);
    arp->opcode = hton16(ARP_OPCODE_REQUEST);
    memcpy(arp->sender_mac, o->if_mac, 6);
    arp->sender_ip = hton32(0);
    memset(arp->target_mac, 0, sizeof(arp->target_mac));
    arp->target_ip = o->addr;
    
    // send packet
    PacketPassInterface_Sender_Send(o->send_if, (uint8_t *)&o->send_packet, sizeof(o->send_packet));
    
    // set sending
    o->send_sending = 1;
}
Esempio n. 3
0
int gtpie_tv8(void *p, unsigned int *length, unsigned int size, uint8_t t, uint64_t v) {
  if ((*length + 9) >= size) return 1;
  ((union gtpie_member*) (p + *length))->tv8.t = hton8(t);
  ((union gtpie_member*) (p + *length))->tv8.v = hton64(v);
  *length += 9;
  return 0;
}
Esempio n. 4
0
int gtpie_tv4(void *p, unsigned int *length, unsigned int size, uint8_t t, uint32_t v) {
  if ((*length + 5) >= size) return 1;
  ((union gtpie_member*) (p + *length))->tv4.t = hton8(t);
  ((union gtpie_member*) (p + *length))->tv4.v = hton32(v);
  *length += 5;
  return 0;
}
Esempio n. 5
0
int gtpie_tv2(void *p, unsigned int *length, unsigned int size, uint8_t t, uint16_t v) {
  if ((*length + 3) >= size) return 1;
  ((union gtpie_member*) (p + *length))->tv2.t = hton8(t);
  ((union gtpie_member*) (p + *length))->tv2.v = hton16(v);
  *length += 3;
  return 0;
}
Esempio n. 6
0
int gtpie_tv0(void *p, unsigned int *length, unsigned int size, uint8_t t, int l, uint8_t *v) {
  if ((*length + 1 + l) >= size) return 1;
  ((union gtpie_member*) (p + *length))->tv0.t = hton8(t);
  memcpy((void*) (p + *length +1), v, l);
  *length += 1 + l;
  return 0;
}
/*** this is a soft close *****************************************************/
void pptp_conn_close(PPTP_CONN * conn, u_int8_t close_reason)
{
    struct pptp_stop_ctrl_conn rqst = {
        PPTP_HEADER_CTRL(PPTP_STOP_CTRL_CONN_RQST), 
        hton8(close_reason), 0, 0
    };
    int i;
  
    assert(conn && conn->call);

    /* avoid repeated close attempts */
    if (conn->conn_state == CONN_IDLE || conn->conn_state == CONN_WAIT_STOP_REPLY) 
        return;

    /* close open calls, if any */
    for (i = 0; i < vector_size(conn->call); i++)
        pptp_call_close(conn, vector_get_Nth(conn->call, i));
    
    /* now close connection */
    log("Closing PPTP connection");
    pptp_send_ctrl_packet(conn, &rqst, sizeof(rqst));
    pptp_reset_timer(); /* wait 60 seconds for reply */
    conn->conn_state = CONN_WAIT_STOP_REPLY;
    return;
}
Esempio n. 8
0
int gtpie_tlv(void *p, unsigned int *length, unsigned int size, uint8_t t, int l, void *v) {
  if ((*length + 3 + l) >= size) return 1;
  ((union gtpie_member*) (p + *length))->tlv.t = hton8(t);
  ((union gtpie_member*) (p + *length))->tlv.l = hton16(l);
  memcpy((void*) (p + *length +3), v, l);
  *length += 3 + l;
  return 0;
}
Esempio n. 9
0
void auth_finished (BSocksClient *o)
{
    // allocate request buffer
    bsize_t size = bsize_fromsize(sizeof(struct socks_request_header));
    switch (o->dest_addr.type) {
        case BADDR_TYPE_IPV4: size = bsize_add(size, bsize_fromsize(sizeof(struct socks_addr_ipv4))); break;
        case BADDR_TYPE_IPV6: size = bsize_add(size, bsize_fromsize(sizeof(struct socks_addr_ipv6))); break;
    }
    if (!reserve_buffer(o, size)) {
        report_error(o, BSOCKSCLIENT_EVENT_ERROR);
        return;
    }
    
    // write request
    struct socks_request_header header;
    header.ver = hton8(SOCKS_VERSION);
    header.cmd = hton8(SOCKS_CMD_CONNECT);
    header.rsv = hton8(0);
    switch (o->dest_addr.type) {
        case BADDR_TYPE_IPV4: {
            header.atyp = hton8(SOCKS_ATYP_IPV4);
            struct socks_addr_ipv4 addr;
            addr.addr = o->dest_addr.ipv4.ip;
            addr.port = o->dest_addr.ipv4.port;
            memcpy(o->buffer + sizeof(header), &addr, sizeof(addr));
        } break;
        case BADDR_TYPE_IPV6: {
            header.atyp = hton8(SOCKS_ATYP_IPV6);
            struct socks_addr_ipv6 addr;
            memcpy(addr.addr, o->dest_addr.ipv6.ip, sizeof(o->dest_addr.ipv6.ip));
            addr.port = o->dest_addr.ipv6.port;
            memcpy(o->buffer + sizeof(header), &addr, sizeof(addr));
        } break;
        default:
            ASSERT(0);
    }
    memcpy(o->buffer, &header, sizeof(header));
    
    // send request
    PacketPassInterface_Sender_Send(o->control.send_if, (uint8_t *)o->buffer, size.value);
    
    // set state
    o->state = STATE_SENDING_REQUEST;
}
Esempio n. 10
0
void connector_handler (BSocksClient* o, int is_error)
{
    DebugObject_Access(&o->d_obj);
    ASSERT(o->state == STATE_CONNECTING)
    
    // check connection result
    if (is_error) {
        // PSIPHON
        // BLog(BLOG_ERROR, "connection failed");
        BLog(BLOG_WARNING, "connection failed");
        goto fail0;
    }
    
    // init connection
    if (!BConnection_Init(&o->con, BConnection_source_connector(&o->connector), o->reactor, o, (BConnection_handler)connection_handler)) {
        BLog(BLOG_ERROR, "BConnection_Init failed");
        goto fail0;
    }
    
    BLog(BLOG_DEBUG, "connected");
    
    // init control I/O
    init_control_io(o);
    
    // check number of methods
    if (o->num_auth_info == 0 || o->num_auth_info > 255) {
        BLog(BLOG_ERROR, "invalid number of authentication methods");
        goto fail1;
    }
    
    // allocate buffer for sending hello
    bsize_t size = bsize_add(
        bsize_fromsize(sizeof(struct socks_client_hello_header)), 
        bsize_mul(
            bsize_fromsize(o->num_auth_info),
            bsize_fromsize(sizeof(struct socks_client_hello_method))
        )
    );
    if (!reserve_buffer(o, size)) {
        goto fail1;
    }
    
    // write hello header
    struct socks_client_hello_header header;
    header.ver = hton8(SOCKS_VERSION);
    header.nmethods = hton8(o->num_auth_info);
    memcpy(o->buffer, &header, sizeof(header));
    
    // write hello methods
    for (size_t i = 0; i < o->num_auth_info; i++) {
        struct socks_client_hello_method method;
        method.method = hton8(o->auth_info[i].auth_type);
        memcpy(o->buffer + sizeof(header) + i * sizeof(method), &method, sizeof(method));
    }
    
    // send
    PacketPassInterface_Sender_Send(o->control.send_if, (uint8_t *)o->buffer, size.value);
    
    // set state
    o->state = STATE_SENDING_HELLO;
    
    return;
    
fail1:
    free_control_io(o);
    BConnection_Free(&o->con);
fail0:
    report_error(o, BSOCKSCLIENT_EVENT_ERROR);
    return;
}
Esempio n. 11
0
/*** encaps_gre ***************************************************************/
int encaps_gre (int fd, void *pack, unsigned int len)
{
    union {
        struct pptp_gre_header header;
        unsigned char buffer[PACKET_MAX + sizeof(struct pptp_gre_header)];
    } u;
    static u_int32_t seq = 1; /* first sequence number sent must be 1 */
    unsigned int header_len;
    int rc;
    /* package this up in a GRE shell. */
    u.header.flags       = hton8 (PPTP_GRE_FLAG_K);
    u.header.ver         = hton8 (PPTP_GRE_VER);
    u.header.protocol    = hton16(PPTP_GRE_PROTO);
    u.header.payload_len = hton16(len);
    u.header.call_id     = hton16(pptp_gre_peer_call_id);
    /* special case ACK with no payload */
    if (pack == NULL) {
        if (ack_sent != seq_recv) {
            u.header.ver |= hton8(PPTP_GRE_FLAG_A);
            u.header.payload_len = hton16(0);
            /* ack is in odd place because S == 0 */
            u.header.seq = hton32(seq_recv);
            ack_sent = seq_recv;
            rc = (*my->write)(fd, &u.header,
                                 sizeof(u.header) - sizeof(u.header.seq));
            if (rc < 0) {
                if (errno == ENOBUFS)
                    rc = 0;         /* Simply ignore it */
                stats.tx_failed++;
            } else if (rc < sizeof(u.header) - sizeof(u.header.seq)) {
                stats.tx_short++;
            } else {
                stats.tx_acks++;
            }
            return rc;
        } else return 0; /* we don't need to send ACK */
    } /* explicit brace to avoid ambiguous `else' warning */
    /* send packet with payload */
    u.header.flags |= hton8(PPTP_GRE_FLAG_S);
    u.header.seq    = hton32(seq);
    if (ack_sent != seq_recv) { /* send ack with this message */
        u.header.ver |= hton8(PPTP_GRE_FLAG_A);
        u.header.ack  = hton32(seq_recv);
        ack_sent = seq_recv;
        header_len = sizeof(u.header);
    } else { /* don't send ack */
        header_len = sizeof(u.header) - sizeof(u.header.ack);
    }
    if (header_len + len >= sizeof(u.buffer)) {
        stats.tx_oversize++;
        return 0; /* drop this, it's too big */
    }
    /* copy payload into buffer */
    memcpy(u.buffer + header_len, pack, len);
    /* record and increment sequence numbers */
    seq_sent = seq; seq++;
    /* write this baby out to the net */
    /* print_packet(2, u.buffer, header_len + len); */
    rc = (*my->write)(fd, u.buffer, header_len + len);
    if (rc < 0) {
        if (errno == ENOBUFS)
            rc = 0;         /* Simply ignore it */
        stats.tx_failed++;
    } else if (rc < header_len + len) {
        stats.tx_short++;
    } else {
        stats.tx_sent++;
        stats.pt.seq  = seq_sent;
        stats.pt.time = time_now_usecs();
    }
    return rc;
}
Esempio n. 12
0
int gtpie_encaps2(union gtpie_member ie[], unsigned int size,
		  void *pack, unsigned *len) {
  unsigned int i, j;
  unsigned char *p;
  unsigned char *end;
  union gtpie_member *m;
  int iesize;
  
  p = pack;

  memset(pack, 0, GTPIE_MAX);
  end = p + GTPIE_MAX;
  for (j=0; j<GTPIE_SIZE; j++) for (i=0; i<size; i++) if (ie[i].t == j) {
    if (GTPIE_DEBUG) printf("gtpie_encaps. Number %d, Type %d\n", i, ie[i].t); 
    m=(union gtpie_member *)p;
    switch (ie[i].t) {
    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:
      iesize = 2;
      break;
    case GTPIE_PFI:             /* TV GTPIE types with value length 2 */
    case GTPIE_CHARGING_C:
    case GTPIE_TRACE_REF:
    case GTPIE_TRACE_TYPE:
      iesize = 3;
      break;
    case GTPIE_QOS_PROFILE0:    /* TV GTPIE types with value length 3 */
    case GTPIE_P_TMSI_S:
      iesize = 4;
      break;
    case GTPIE_TLLI:            /* TV GTPIE types with value length 4 */
    case GTPIE_P_TMSI:
    case GTPIE_TEI_DI:
    case GTPIE_TEI_C:
      iesize = 5;
      break;
    case GTPIE_TEI_DII:         /* TV GTPIE types with value length 5 */
      iesize = 6;
      break;
    case GTPIE_RAB_CONTEXT:     /* TV GTPIE types with value length 7 */
      iesize = 8;
      break;
    case GTPIE_IMSI:            /* TV GTPIE types with value length 8 */
    case GTPIE_RAI:
      iesize = 9;
      break;
    case GTPIE_AUTH_TRIPLET:    /* TV GTPIE types with value length 28 */
      iesize = 29;
      break;
    case GTPIE_EXT_HEADER_T:   /* GTP extension header */
      iesize = 2 + hton8(ie[i].ext.l);
      break;
    case GTPIE_CHARGING_ID:    /* TLV GTPIE types with length length 2 */
    case GTPIE_EUA:
    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:
      iesize = 3 + hton16(ie[i].tlv.l);
      break;
    default:
      return 2; /* We received something unknown */
    }
    if (p+iesize < end) {
      memcpy(p, &ie[i], iesize);
      p += iesize;
      *len += iesize;
    }
    else return 2;              /* Out of space */
  }
  return 0;
}
Esempio n. 13
0
/*** 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;
}
Esempio n. 14
0
/*** encaps_gre ***************************************************************/
int encaps_gre (int fd, void *pack, unsigned int len)
{
    union {
        struct pptp_gre_header header;
        unsigned char buffer[PACKET_MAX + sizeof(struct pptp_gre_header)];
    } u;
    //static u_int32_t seq = 1; /* first sequence number sent must be 1 */
    unsigned int header_len;
    int rc;
    /*  added start, Winster Chan, 06/26/2006 */
    static u_int32_t kerseq; /* Sequence number got from kernel by ioctl() */
    /*  added end, Winster Chan, 06/26/2006 */

    /* package this up in a GRE shell. */
    u.header.flags       = hton8 (PPTP_GRE_FLAG_K);
    u.header.ver         = hton8 (PPTP_GRE_VER);
    u.header.protocol    = hton16(PPTP_GRE_PROTO);
    u.header.payload_len = hton16(len);
    u.header.call_id     = hton16(pptp_gre_peer_call_id);
    /* special case ACK with no payload */
    if (pack == NULL) {
        if (ack_sent != seq_recv) {
            u.header.ver |= hton8(PPTP_GRE_FLAG_A);
            u.header.payload_len = hton16(0);
            /* ack is in odd place because S == 0 */
            u.header.seq = hton32(seq_recv);
            ack_sent = seq_recv;
            rc = write(fd, &u.header, sizeof(u.header) - sizeof(u.header.seq));
            if (rc < 0) {
                stats.tx_failed++;
            } else if (rc < sizeof(u.header) - sizeof(u.header.seq)) {
                stats.tx_short++;
            } else {
                stats.tx_acks++;
            }
            return rc;
        } else return 0; /* we don't need to send ACK */
    } /* explicit brace to avoid ambiguous `else' warning */
    /* send packet with payload */
    u.header.flags |= hton8(PPTP_GRE_FLAG_S);
    /*  modified start, Winster Chan, 06/26/2006 */
    //u.header.seq    = hton32(seq);
    if (pox_fd >= 0) {
    	if (ioctl(pox_fd, PPTPIOCGGRESEQ, &kerseq) == -1) {
            warn("Couldn't get GRE sequence number");
        }
	}
	else
        warn("Socket not opened");
    u.header.seq    = hton32(kerseq);
    /*  modified end, Winster Chan, 06/26/2006 */
    if (ack_sent != seq_recv) { /* send ack with this message */
        u.header.ver |= hton8(PPTP_GRE_FLAG_A);
        u.header.ack  = hton32(seq_recv);
        ack_sent = seq_recv;
        header_len = sizeof(u.header);
    } else { /* don't send ack */
        header_len = sizeof(u.header) - sizeof(u.header.ack);
    }
    if (header_len + len >= sizeof(u.buffer)) {
        stats.tx_oversize++;
        return 0; /* drop this, it's too big */
    }
    /* copy payload into buffer */
    memcpy(u.buffer + header_len, pack, len);
    /* record and increment sequence numbers */
    /*  modified start, Winster Chan, 06/26/2006 */
    //seq_sent = seq; seq++;
    /*
     * Note: the kerseq(kernel sequence number) is maintained by
     *       pptp kernel driver
     */
    seq_sent = kerseq;
    /*  modified end, Winster Chan, 06/26/2006 */
    /* write this baby out to the net */
    /* print_packet(2, u.buffer, header_len + len); */
    rc = write(fd, u.buffer, header_len + len);
    if (rc < 0) {
        stats.tx_failed++;
    } else if (rc < header_len + len) {
        stats.tx_short++;
    } else {
        stats.tx_sent++;
        stats.pt.seq  = seq_sent;
        stats.pt.time = time_now_usecs();
    }
    return rc;
}