コード例 #1
0
ファイル: gtpie.c プロジェクト: Dosxiong/learngit
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;
}
コード例 #2
0
ファイル: BSocksClient.c プロジェクト: projectarkc/psiphon
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);
}
コード例 #3
0
ファイル: pptp_gre.c プロジェクト: WiseMan787/ralink_sdk
/*** 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;
}
コード例 #4
0
ファイル: gtpie.c プロジェクト: Dosxiong/learngit
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 */
  }
}
コード例 #5
0
ファイル: pptp_ctrl.c プロジェクト: a170785/buildroot
/*** 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;
}
コード例 #6
0
ファイル: BArpProbe.c プロジェクト: 0wsqqsw/lantern
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;
    }
}