int serial_send(int node, int op, const uint8_t *data, int len) { uint8_t buf[1 + SPACKET_SIZE + MFSMSG_SIZE]; memset(buf, 0, sizeof buf); tmsg_t *spacket_header, *msg; buf[0] = 0; spacket_header = new_tmsg(buf + 1, SPACKET_SIZE); spacket_header_dest_set(spacket_header, 0xffff); spacket_header_length_set(spacket_header, MFSMSG_SIZE); spacket_header_type_set(spacket_header, MFSMSG_AM_TYPE); msg = new_tmsg(buf + 1 + SPACKET_SIZE, MFSMSG_SIZE); mfsmsg_node_set(msg, node); mfsmsg_op_set(msg, op); if (len > MFS_DATA_SIZE) len = MFS_DATA_SIZE; set_data(msg, data, len); DEBUG_PACKET(buf); return (src_type == SRC_DEVICE) ? write_serial_packet(src_dev, buf, sizeof buf) : write_sf_packet(src_fd, buf, sizeof buf); }
void make_echo_req_packet(struct pptp_out_call_rply *rply_packet, ssize_t * rply_size, u_int32_t echo_id) { struct pptp_echo_rqst echo_packet; MAKE_CTRL_HEADER(echo_packet, ECHO_RQST); echo_packet.identifier = echo_id; COPY_CTRL_PACKET(echo_packet, rply_packet, rply_size); DEBUG_PACKET("ECHO REQ"); }
void make_stop_ctrl_req(struct pptp_out_call_rply *rply_packet, ssize_t * rply_size) { struct pptp_stop_ctrl_conn_rqst stop_ctrl; MAKE_CTRL_HEADER(stop_ctrl, STOP_CTRL_CONN_RQST); stop_ctrl.reason = GENERAL_STOP_CTRL; stop_ctrl.reserved1 = RESERVED; stop_ctrl.reserved2 = htons(RESERVED); COPY_CTRL_PACKET(stop_ctrl, rply_packet, rply_size); DEBUG_PACKET("STOP CTRL REQ"); }
/* * deal_stop_ctrl_conn * * This method response to a STOP-CONTROL-CONNECTION-REQUEST with a * STOP-CONTROL-CONNECTION-REPLY. */ void deal_stop_ctrl_conn(void *packet, struct pptp_out_call_rply *rply_packet, ssize_t * rply_size) { struct pptp_stop_ctrl_conn_rply stop_ctrl_conn_rply; MAKE_CTRL_HEADER(stop_ctrl_conn_rply, STOP_CTRL_CONN_RPLY); stop_ctrl_conn_rply.result_code = DISCONNECTED; stop_ctrl_conn_rply.error_code = NO_ERROR; stop_ctrl_conn_rply.reserved1 = htons(RESERVED); COPY_CTRL_PACKET(stop_ctrl_conn_rply, rply_packet, rply_size); DEBUG_PACKET("STOP CTRL CONN RPLY"); }
/* * deal_echo * * This method 'deals' with a ECHO-REQUEST. After stripping down the * connection request a suitable reply is formed and stored in * 'rply_packet' ready for sending. * * args: packet (IN) - the packet that we have to deal with (should be a * ECHO-REQUEST packet) * rply_packet (OUT) - suitable reply to the 'packet' we got. * rply_size (OUT) - size of the reply packet * */ void deal_echo(unsigned char *packet, struct pptp_out_call_rply *rply_packet, ssize_t * rply_size) { struct pptp_echo_rqst *echo_rqst; struct pptp_echo_rply echo_rply; echo_rqst = (struct pptp_echo_rqst *) packet; MAKE_CTRL_HEADER(echo_rply, ECHO_RPLY); echo_rply.identifier = echo_rqst->identifier; echo_rply.result_code = CONNECTED; echo_rply.error_code = NO_ERROR; echo_rply.reserved1 = htons(RESERVED); COPY_CTRL_PACKET(echo_rply, rply_packet, rply_size); DEBUG_PACKET("ECHO RPLY"); }
int serial_receive(int *node, int *op, int *result, uint8_t *data, int len) { uint8_t *buf; tmsg_t *msg; unsigned char *packet; int packet_len; packet = (src_type == SRC_DEVICE) ? read_serial_packet(src_dev, &packet_len) : read_sf_packet(src_fd, &packet_len); if (!packet) return -1; DEBUG_PACKET(packet); /* skip the header */ buf = packet + 1 + SPACKET_SIZE; packet_len -= 1 + SPACKET_SIZE; if (packet_len > MFSMSG_SIZE) { fprintf(stderr, "packet too big: %d\n", len); packet_len = MFSMSG_SIZE; } msg = new_tmsg(buf, MFSMSG_SIZE); if (node) *node = mfsmsg_node_get(msg); if (op) *op = mfsmsg_op_get(msg); if (result) *result = mfsmsg_result_get(msg); if (len > packet_len) len = packet_len; get_data(msg, data, len); free(packet); return len; }
/* * deal_start_ctrl_conn * * This method 'deals' with a START-CONTROL-CONNECTION-REQUEST. After * stripping down the connection request a suitable reply is formed and * stored in 'rply_packet' ready for sending. * * args: packet (IN) - the packet that we have to deal with (should be a * START-CONTROL-CONNECTION-REQUEST packet) * rply_packet (OUT) - suitable reply to the 'packet' we got. * rply_size (OUT) - size of the reply packet */ void deal_start_ctrl_conn(void *packet, struct pptp_out_call_rply *rply_packet, ssize_t * rply_size) { struct pptp_start_ctrl_conn_rply start_ctrl_conn_rply; MAKE_CTRL_HEADER(start_ctrl_conn_rply, START_CTRL_CONN_RPLY); start_ctrl_conn_rply.version = htons(PPTP_VERSION); start_ctrl_conn_rply.result_code = CONNECTED; start_ctrl_conn_rply.error_code = NO_ERROR; start_ctrl_conn_rply.framing_cap = htons(OUR_FRAMING); start_ctrl_conn_rply.bearer_cap = htons(OUR_BEARER); start_ctrl_conn_rply.max_channels = htons(MAX_CHANNELS); start_ctrl_conn_rply.firmware_rev = htons(PPTP_FIRMWARE_VERSION); memset(start_ctrl_conn_rply.hostname, 0, MAX_HOSTNAME_SIZE); strncpy((char *)start_ctrl_conn_rply.hostname, PPTP_HOSTNAME, MAX_HOSTNAME_SIZE); memset(start_ctrl_conn_rply.vendor, 0, MAX_VENDOR_SIZE); strncpy((char *)start_ctrl_conn_rply.vendor, PPTP_VENDOR, MAX_VENDOR_SIZE); COPY_CTRL_PACKET(start_ctrl_conn_rply, rply_packet, rply_size); DEBUG_PACKET("START CTRL CONN RPLY"); }
/* * deal_out_call * * This method 'deals' with a OUT-GOING-CALL-REQUEST. After * stripping down the request a suitable reply is formed and stored in * 'rply_packet' ready for sending. * * args: packet (IN) - the packet that we have to deal with (should be a * OUT-GOING-CALL-REQUEST packet) * rply_packet (OUT) - suitable reply to the 'packet' we got. * rply_size (OUT) - size of the reply packet * */ void deal_out_call(unsigned char *packet, struct pptp_out_call_rply *rply_packet, ssize_t * rply_size) { u_int16_t pac_call_id; struct pptp_out_call_rqst *out_call_rqst; struct pptp_out_call_rply out_call_rply; out_call_rqst = (struct pptp_out_call_rqst *) packet; if ((pac_call_id = getcall()) == htons(-1)) { /* XXX should reject call */ syslog(LOG_ERR, "CTRL: No free Call IDs!"); pac_call_id = 0; } MAKE_CTRL_HEADER(out_call_rply, OUT_CALL_RPLY); /* call_id is used for ctrl, call_id_peer is used for GRE * call_id_peer is what we were sent by the other end in ctrl initilization */ out_call_rply.call_id = pac_call_id; out_call_rply.call_id_peer = out_call_rqst->call_id; out_call_rply.result_code = CONNECTED; out_call_rply.error_code = NO_ERROR; out_call_rply.cause_code = NO_ERROR; /* maybe limit to pppd speed? but pppd doesn't accept 10Mbps as a speed and yet * still performs at over 115200, eg, 60kbyte/sec and higher observed. */ out_call_rply.speed = out_call_rqst->max_bps; /* lets match their window size for now... was htons(PCKT_RECV_WINDOW_SIZE) */ out_call_rply.pckt_recv_size = out_call_rqst->pckt_recv_size; window=htons(out_call_rply.pckt_recv_size); if(pptpctrl_debug) syslog(LOG_DEBUG, "CTRL: Set parameters to %d maxbps, %d window size", ntohl(out_call_rply.speed), ntohs(out_call_rply.pckt_recv_size)); out_call_rply.pckt_delay = htons(PCKT_PROCESS_DELAY); out_call_rply.channel_id = htonl(CHANNEL_ID); COPY_CTRL_PACKET(out_call_rply, rply_packet, rply_size); DEBUG_PACKET("OUT CALL RPLY"); }
void make_call_admin_shutdown(struct pptp_out_call_rply *rply_packet, ssize_t * rply_size) { struct pptp_call_disconn_ntfy call_disconn_ntfy; u_int16_t pac_call_id; /* Form a reply * The reply packet is a CALL-DISCONECT-NOTIFY * In single call mode we don't care what peer's call ID is, so don't even bother looking */ if ((pac_call_id = freecall()) == htons(-1)) { /* XXX should return an error */ syslog(LOG_ERR, "CTRL: Could not free Call ID [admin shutdown]!"); } MAKE_CTRL_HEADER(call_disconn_ntfy, CALL_DISCONN_NTFY); call_disconn_ntfy.call_id = pac_call_id; call_disconn_ntfy.result_code = ADMIN_SHUTDOWN; /* disconnected by admin shutdown */ call_disconn_ntfy.error_code = NO_ERROR; call_disconn_ntfy.cause_code = htons(NO_ERROR); call_disconn_ntfy.reserved1 = htons(RESERVED); memset(call_disconn_ntfy.call_stats, 0, 128); COPY_CTRL_PACKET(call_disconn_ntfy, rply_packet, rply_size); DEBUG_PACKET("CALL DISCONNECT RPLY"); }
/* * deal_call_clr * * This method 'deals' with a CALL-CLEAR-REQUEST. After stripping down the * connection request a suitable reply is formed and stored in * 'rply_packet' ready for sending. * * args: packet (IN) - the packet that we have to deal with (should be a * CALL-CLEAR-REQUEST packet) * rply_packet (OUT) - suitable reply to the 'packet' we got. * rply_size (OUT) - size of the reply packet * */ void deal_call_clr(unsigned char *packet, unsigned char *rply_packet, ssize_t *rply_size) { struct pptp_call_disconn_ntfy call_disconn_ntfy; u_int16_t pac_call_id; /* Form a reply * The reply packet is a CALL-DISCONECT-NOTIFY * In single call mode we don't care what peer's call ID is, so don't even bother looking */ if ((pac_call_id = freecall()) == htons(-1)) { /* XXX should return an error */ syslog(LOG_ERR, "CTRL: Could not free Call ID [call clear]!"); } MAKE_CTRL_HEADER(call_disconn_ntfy, CALL_DISCONN_NTFY); call_disconn_ntfy.call_id = pac_call_id; call_disconn_ntfy.result_code = CALL_CLEAR_REQUEST; /* disconnected by call_clr_rqst */ call_disconn_ntfy.error_code = NO_ERROR; call_disconn_ntfy.cause_code = htons(NO_ERROR); call_disconn_ntfy.reserved1 = htons(RESERVED); memset(call_disconn_ntfy.call_stats, 0, 128); COPY_CTRL_PACKET(call_disconn_ntfy, rply_packet, rply_size); DEBUG_PACKET("CALL DISCONNECT RPLY"); }