/* resend una packets */ static int l2tp_ctrl_resend_una_packets(l2tp_ctrl *_this) { uint16_t seq; bytebuffer *bytebuf; struct l2tp_header *header; int nsend; nsend = 0; for (seq = _this->snd_una; SEQ_LT(seq, _this->snd_nxt); seq++) { bytebuf = _this->snd_buffers[seq % _this->winsz]; header = bytebuffer_pointer(bytebuf); header->nr = htons(_this->rcv_nxt); #ifdef L2TP_CTRL_DEBUG if (debuglevel >= 3) { l2tp_ctrl_log(_this, DEBUG_LEVEL_3, "RESEND seq=%u", ntohs(header->ns)); show_hd(debug_get_debugfp(), bytebuffer_pointer(bytebuf), bytebuffer_remaining(bytebuf)); } #endif if (l2tp_ctrl_send(_this, bytebuffer_pointer(bytebuf), bytebuffer_remaining(bytebuf)) < 0) { l2tp_ctrl_log(_this, LOG_ERR, "sendto() failed in %s: %m", __func__); return -1; } nsend++; } return nsend; }
/* send control packet */ int l2tp_ctrl_send_packet(l2tp_ctrl *_this, int call_id, bytebuffer *bytebuf) { struct l2tp_header *hdr; int rval; time_t curr_time; curr_time = get_monosec(); bytebuffer_flip(bytebuf); hdr = (struct l2tp_header *)bytebuffer_pointer(bytebuf); memset(hdr, 0, sizeof(*hdr)); hdr->t = 1; hdr->ver = L2TP_HEADER_VERSION_RFC2661; hdr->l = 1; hdr->length = htons(bytebuffer_remaining(bytebuf)); hdr->tunnel_id = htons(_this->peer_tunnel_id); hdr->session_id = htons(call_id); hdr->s = 1; hdr->ns = htons(_this->snd_nxt); hdr->nr = htons(_this->rcv_nxt); if (bytebuffer_remaining(bytebuf) > sizeof(struct l2tp_header)) /* Not ZLB */ _this->snd_nxt++; L2TP_CTRL_DBG((_this, DEBUG_LEVEL_2, "SEND C ns=%u nr=%u snd_nxt=%u snd_una=%u rcv_nxt=%u ", ntohs(hdr->ns), htons(hdr->nr), _this->snd_nxt, _this->snd_una, _this->rcv_nxt)); if (L2TP_CTRL_CONF(_this)->ctrl_out_pktdump != 0) { l2tpd_log(_this->l2tpd, LOG_DEBUG, "L2TP Control output packet dump"); show_hd(debug_get_debugfp(), bytebuffer_pointer(bytebuf), bytebuffer_remaining(bytebuf)); } if ((rval = l2tp_ctrl_send(_this, bytebuffer_pointer(bytebuf), bytebuffer_remaining(bytebuf))) < 0) { L2TP_CTRL_DBG((_this, LOG_DEBUG, "sendto() failed: %m")); } _this->last_snd_ctrl = curr_time; return (rval == bytebuffer_remaining(bytebuf))? 0 : 1; }
/* Some route implementation which has "PPTP pass-through" function * will discard 1723/tcp packet between PAC and PNS, when it recognize * SLI from PAC. (for example, FLASHWAVE by Fujitsu). * * To avoid avobe situation, npppd send well-known SLI only. */ static int pptp_call_send_SLI(pptp_call *_this) { int lpkt; struct pptp_sli *sli; sli = bytebuffer_pointer(_this->ctrl->send_buf); lpkt = bytebuffer_remaining(_this->ctrl->send_buf); if (lpkt < sizeof(struct pptp_sli)) { pptp_call_log(_this, LOG_ERR, "SendOCRP failed: No buffer space available"); return -1; } memset(sli, 0, sizeof(struct pptp_sli)); pptp_init_header(&sli->header, sizeof(struct pptp_sli), PPTP_CTRL_MES_CODE_SLI); sli->peers_call_id = _this->id; sli->send_accm = 0xffffffff; sli->recv_accm = 0xffffffff; _this->last_io = get_monosec(); pptp_call_log(_this, LOG_INFO, "SendSLI accm=%08x:%08x", sli->send_accm, sli->recv_accm); sli->peers_call_id = htons(sli->peers_call_id); sli->send_accm = htonl(sli->send_accm); sli->recv_accm = htonl(sli->recv_accm); pptp_ctrl_output(_this->ctrl, NULL, sizeof(struct pptp_sli)); return 0; }
static int pppoe_session_send_PADT(pppoe_session *_this) { u_char bufspace[2048]; bytebuffer *buf; struct pppoe_header pppoe; int rval = 0; struct pppoe_tlv tlv; if ((buf = bytebuffer_wrap(bufspace, sizeof(bufspace))) == NULL) { pppoe_session_log(_this, LOG_ERR, "bytebuffer_wrap() failed on %s(): %m", __func__); return -1; } bytebuffer_clear(buf); /* * PPPoE Header */ memset(&pppoe, 0, sizeof(pppoe)); pppoe.ver = PPPOE_RFC2516_VER; pppoe.type = PPPOE_RFC2516_TYPE; pppoe.code = PPPOE_CODE_PADT; pppoe.session_id = htons(_this->session_id); bytebuffer_put(buf, &pppoe, sizeof(pppoe)); /* * Tag - End-of-List */ tlv.type = htons(PPPOE_TAG_END_OF_LIST); tlv.length = 0; bytebuffer_put(buf, &tlv, sizeof(tlv)); tlv.type = htons(PPPOE_TAG_END_OF_LIST); tlv.length = 0; bytebuffer_put(buf, &tlv, sizeof(tlv)); bytebuffer_flip(buf); if (pppoe_session_output(_this, 1, bytebuffer_pointer(buf), bytebuffer_remaining(buf)) != 0) { pppoe_session_log(_this, LOG_ERR, "pppoed_output failed: %m"); rval = 1; } pppoe_session_log(_this, LOG_INFO, "SendPADT"); bytebuffer_unwrap(buf); bytebuffer_destroy(buf); return rval; }
/* send L2TP data message */ static int l2tp_call_send_data_packet(l2tp_call *_this, bytebuffer *buffer) { int rval; struct l2tp_header *hdr; bytebuffer_flip(buffer); hdr = (struct l2tp_header *)bytebuffer_pointer(buffer); memset(hdr, 0, sizeof(*hdr) - 4); /* Nr, NS are option */ hdr->t = 0; hdr->ver = L2TP_HEADER_VERSION_RFC2661; hdr->l = 1; hdr->length = htons(bytebuffer_remaining(buffer)); hdr->tunnel_id = htons(_this->ctrl->peer_tunnel_id); hdr->session_id = htons(_this->peer_session_id); if (_this->use_seq) { hdr->s = 1; hdr->ns = htons(_this->snd_nxt++); hdr->nr = htons(_this->rcv_nxt); } if (L2TP_CTRL_CONF(_this->ctrl)->data_out_pktdump != 0) { l2tpd_log(_this->ctrl->l2tpd, LOG_DEBUG, "ctrl=%u call=%u L2TP Data output packet dump", _this->ctrl->id, _this->id); show_hd(debug_get_debugfp(), bytebuffer_pointer(buffer), bytebuffer_remaining(buffer)); } if ((rval = l2tp_ctrl_send(_this->ctrl, bytebuffer_pointer(buffer), bytebuffer_remaining(buffer))) < 0) { L2TP_CALL_DBG((_this, LOG_DEBUG, "sendto() failed: %m")); } return (rval == bytebuffer_remaining(buffer))? 0 : 1; }
/* Send Outgoing-Call-Reply */ static int pptp_call_send_OCRP(pptp_call *_this, int result, int error, int cause) { int lpkt; struct pptp_ocrp *ocrp; char logbuf[512]; ocrp = bytebuffer_pointer(_this->ctrl->send_buf); lpkt = bytebuffer_remaining(_this->ctrl->send_buf); if (lpkt < sizeof(struct pptp_ocrp)) { pptp_call_log(_this, LOG_ERR, "SendOCRP failed: No buffer space available"); return -1; } memset(ocrp, 0, sizeof(struct pptp_ocrp)); pptp_init_header(&ocrp->header, sizeof(struct pptp_ocrp), PPTP_CTRL_MES_CODE_OCRP); ocrp->call_id = _this->id; ocrp->peers_call_id = _this->peers_call_id; ocrp->result_code = result; ocrp->error_code = error; ocrp->cause_code = cause; ocrp->connect_speed = PPTP_CALL_CONNECT_SPEED; ocrp->recv_winsz = _this->maxwinsz; ocrp->packet_proccessing_delay = PPTP_CALL_INITIAL_PPD; ocrp->physical_channel_id = _this->id; pptp_call_OCRP_string(ocrp, logbuf, sizeof(logbuf)); pptp_call_log(_this, LOG_INFO, "SendOCRP %s", logbuf); ocrp->call_id = htons(ocrp->call_id); ocrp->peers_call_id = htons(ocrp->peers_call_id); ocrp->cause_code = htons(ocrp->cause_code); ocrp->connect_speed = htons(ocrp->connect_speed); ocrp->recv_winsz = htons(ocrp->recv_winsz); ocrp->packet_proccessing_delay = htons(ocrp->packet_proccessing_delay); ocrp->physical_channel_id = htonl(ocrp->physical_channel_id); _this->last_io = get_monosec(); pptp_ctrl_output(_this->ctrl, NULL, sizeof(struct pptp_ocrp)); return 0; }
/* Send Call-Disconnect-Notify */ static void pptp_call_send_CDN(pptp_call *_this, int result, int error, int cause, const char *statistics) { int lpkt; struct pptp_cdn *cdn; cdn = bytebuffer_pointer(_this->ctrl->send_buf); lpkt = bytebuffer_remaining(_this->ctrl->send_buf); if (lpkt < sizeof(struct pptp_cdn)) { pptp_call_log(_this, LOG_ERR, "SendCCR failed: No buffer space available"); return; } memset(cdn, 0, sizeof(struct pptp_cdn)); pptp_init_header(&cdn->header, sizeof(struct pptp_cdn), PPTP_CTRL_MES_CODE_CDN); cdn->call_id = _this->id; cdn->result_code = result; cdn->error_code = error; cdn->cause_code = cause; if (statistics != NULL) strlcpy(cdn->statistics, statistics, sizeof(cdn->statistics)); pptp_call_log(_this, LOG_INFO, "SendCDN " "call_id=%u result=%s(%d) error=%s(%d) cause=%d statistics=%s", cdn->call_id, pptp_CDN_result_string(cdn->result_code), cdn->result_code, pptp_general_error_string(cdn->error_code), cdn->error_code, cdn->cause_code, (statistics == NULL)? "(none)" : (char *)cdn->statistics); cdn->call_id = htons(cdn->call_id); cdn->cause_code = htons(cdn->cause_code); _this->last_io = get_monosec(); pptp_ctrl_output(_this->ctrl, NULL, sizeof(struct pptp_cdn)); }
/* send PADS */ static int pppoe_session_send_PADS(pppoe_session *_this, struct pppoe_tlv *hostuniq, struct pppoe_tlv *service_name) { int rval, len; u_char bufspace[2048], msgbuf[80]; bytebuffer *buf; struct pppoe_header pppoe; struct pppoe_tlv tlv; if ((buf = bytebuffer_wrap(bufspace, sizeof(bufspace))) == NULL) { pppoe_session_log(_this, LOG_ERR, "bytebuffer_wrap() failed on %s(): %m", __func__); return -1; } bytebuffer_clear(buf); /* * PPPoE Header */ memset(&pppoe, 0, sizeof(pppoe)); pppoe.ver = PPPOE_RFC2516_VER; pppoe.type = PPPOE_RFC2516_TYPE; pppoe.code = PPPOE_CODE_PADS; pppoe.session_id = htons(_this->session_id); bytebuffer_put(buf, &pppoe, sizeof(pppoe)); /* * Tag - Service-Name */ msgbuf[0] = '\0'; if (service_name != NULL) { tlv.type = htons(PPPOE_TAG_SERVICE_NAME); tlv.length = htons(service_name->length); bytebuffer_put(buf, &tlv, sizeof(tlv)); len = service_name->length; if (len > 0) { bytebuffer_put(buf, service_name->value, len); strlcpy(msgbuf, service_name->value, MIN(len + 1, sizeof(msgbuf))); } } /* * Tag - Host-Uniq */ if (hostuniq != NULL) { tlv.type = htons(PPPOE_TAG_HOST_UNIQ); tlv.length = htons(hostuniq->length); bytebuffer_put(buf, &tlv, sizeof(tlv)); bytebuffer_put(buf, hostuniq->value, hostuniq->length); } tlv.type = htons(PPPOE_TAG_END_OF_LIST); tlv.length = 0; bytebuffer_put(buf, &tlv, sizeof(tlv)); bytebuffer_flip(buf); rval = 0; if (pppoe_session_output(_this, 1, bytebuffer_pointer(buf), bytebuffer_remaining(buf)) != 0) { pppoe_session_log(_this, LOG_ERR, "pppoed_output failed: %m"); rval = 1; } pppoe_session_log(_this, LOG_INFO, "SendPADS serviceName=%s " "hostUniq=%s", msgbuf, hostuniq? pppoed_tlv_value_string(hostuniq) : "none"); bytebuffer_unwrap(buf); bytebuffer_destroy(buf); return rval; }